主题
Kubernetes 学习记录
需求产生原因:
docker虚拟化之后,在集群环境下,会产生端口混乱问题。 分布式环境下管理多个服务很是麻烦,需要在不同的机器启动, 比如宿主机开启三个tomcat,进行分布式,端口映射就是一个很麻烦的问题。
kubernetes是什么: kubernetes相当于一个docker的管家,他承包了docker的网络配置,磁盘持久化存储,负责了多个docker分布式启动,支持扩缩容,宕机自动重启等一系列操作,所以k8s 又称为容器编排服务框架。当然,在使用的时候这时候就得有一套k8s的操作命令了,通过k8s的命令来操作docker的行为。 当然,想要彻底理解k8s,一系列的概念就必须要学习了
1. 简介
- 资源管理器 :
apache mesos (twitter曾经使用过,2019
-5后改为Kubernetes)
Docker Swarm :
Kubernetes:是有google公司根据自己的资源管理器borg,使用go语言开发而来。
Kubernetes特性:
开源
轻量级
弹性伸缩(动态不停服务的增减服务硬件)
负载均衡 : IPVS
知识图谱:
介绍说明:前生今世 Kubernetes框架 Kubernetes关键字
基础概念: 什么是Pod 、 控制器类型、K8S 、网络通讯模式
Kubernetes: 构建K8S集群
资源清单:资源、掌握资源清单的语法、编写Pod、掌握Pod的生命周期(重要)
Pod控制器: 掌握各种控制器的特点以及使用定义方式。
服务发现: 掌握SVC原理及其构建方式
存储: 掌握多种存储类型的特点、并且能够在不同环境中选择合适的存储方案(有自己的见解)
调度器: 掌握调度器原理、能够根据要求吧Pod定义到想要的节点运行
安全:集群的认证、鉴权、访问控制、原理及其流程
HELM:类似于linux yum、掌握HEML原理、HELM模板定义、HELM部署一些常用插件
运维:修改Kubeadm 达到证书可用期限为10年、能够构建高可用的Kubernetes集群
Kubernetes 核心概念s
- Pod
- 最小部署单元
- 一组容器的集合
- 共享网络
- 生命周期是短暂的
- controller
- 确保预期的pod副本数量
- 无状态应用部署
- 有状态应用部署
- 确保所有的node运行同一个pod
- 一次任务和定时任务
- service
- 定义一组pod的访问规则
- Pod
k8s架构
历史关系进程说明:
蜜月期:开始市面只有k8s 一个编排容器,也只有一个容器环境 docker,
后来k8s慢慢做大,有了一个容器接口cri,并有k8s提供跟docker的兼容,因此产生dockershim。后来dockersshim独立出去。在后来k8s 1.24后剔除dockersshim。
此时市面上只有k8s一家独大,docker只能自己开发cri-dockerd对其兼容。
K8s 集群部署
搭建k8s 环境平台规划
a) 单master
b) 多master
- 多master ,master 跟node之间多了一层负载均衡
硬件要求
shell
#集群初始化
kubeadm init \
--control-plane-endpoint="master1.com" \
--kubernetes-version=v1.21.14 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.96.0.0/16 \
--token-ttl=0 \
--cri-socket unix:///run/cri-dockerd.sock \
--upload-certs
##--token-ttl duration 默认值:24h0m0s
##令牌被自动删除之前的持续时间(例如 1 s,2 m,3 h)。
##如果设置为 '0',则令牌将永不过期
安装dashboard
- 安装
shell
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
更改网络类型为NodePort
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
type: NodePort
创建用户
yamlapiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kubernetes-dashboard
创建规则绑定
yamlapiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kubernetes-dashboard
获取token
shell
kubectl -n kubernetes-dashboard create token admin-user
上面无法执行使用下面的,github官方命令是上面的,但是我这个k8s版本安装后执行失败。
kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"
2 k8s 基础概念
2.1. 资源创建方式
- 命令行
- YAML
- yaml字段说明查看命令
kubectl explain pod.spec
- yaml字段说明查看命令
2.2. namespace
名称空间用来隔离资源
kubectl create ns hello
kubectl delete ns hello
yaml
apiVersion: v1
kind: Namespace
metadata:
name: hello
2.3. Pod
pod是k8s中最小单位,一个pod中可以运行多个容器。
命令操作
shell
> 创建一个nginxpod
> kubectl run mynginx --image=nginx
> 查看pod
> kubectl get pods # 默认查看default命名空间的pod
> 检查pod
> kubectl describe pod mynginx # mynginx 为 pod的名称通过kubectl get pods 获取
> 删除 pod
> kubectl delete pod mynginx
`查看pod日志`
> kubectl logs mynginx
> 输出:nginx启动日志
> kubectl logs -f mynginx
> 输出:一直输出实时内容,类似tail -f
# 每个pod - k8s 都会分配一个ip
kubectl get pod -o wide
#使用pod的ip+pod里面运行容器的端口
curl 10.244.3.8:80
#进入nginx 更改页面
kubectl exec -it mynginx -- /bin/bash
`注意:`集群中任意的一个机器或应用都可以访问pod的ip
yaml操作
yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: mynginx
name: mynginx
spec:
containers:
- image: nginx
name: mynginx
shell
# 创建
kubectl apply -f pod.yaml
# 删除
kubectl delete -f pod.yaml
一个pod多个容器
- 特性;
- 同一个pod内的容器
- 共享网络空间,例如nginx的容器访问tomcat,直接访问127.0.0.1:8080
- 共享存储,
yml
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp
name: myapp
spec:
containers:
- image: nginx
name: mynginx
- image: tomcat
name: mytomcat
2.4 pod生命周期
pod创建过程
pod的终止过程
2.4. Deployment
控制Pod,使Pod拥有多副本,自愈,扩容缩能力。
2.4.1 自愈能力
命令行操作
shell
#创建一个nginx通过deployment
kubectl create deployment mynginx --image=nginx
>
➜ ~ kubectl get pods
NAME READY STATUS RESTARTS AGE
mynginx-ff886775c-78rrl 1/1 Running 0 21m
>
#通过删除pod的命令删除
kubectl delete pod mynginx-ff886775c-78rrl >这个不会真正的删除,会删掉这个重启另一个,体现了k8s的自愈能力
#查看deployment
kubectl get deployment -owide
#真正删除deployment
➜ ~ kubectl delete deployment mynginx
2.4.2 多副本
后缀 --replicas=3
shell
kubectl create deployment mynginx --image=nginx --replicas=3
2.4.3 自动扩缩容
命令行操作
//扩容到5个:
kubectl sacle deploy/mynginx --replicas=5
命令行操作yaml配置文件
kubectl edit deploy mynginx
spec:
progressDeadlineSeconds: 600
replicas: 3
revisionHistoryLimit: 10
2.4.4 滚动更新
滚动更新本质是更换镜像,等一个pod启动一个新的,停止一个旧的,从而完成滚动更新。
命令操作行
kubectl set image deploy/mynginx nginx=nginx:1.16.1 --record
注: --record 记录下来变更
2.4.5 版本回退
shell
# 历史记录
kubectl rollout history deployment/mynginx
=》结果
➜ ~ kubectl rollout history deployment/mynginx
deployment.apps/mynginx
REVISION CHANGE-CAUSE
1 <none>
2 kubectl set image deploy/mynginx nginx=nginx:1.16.1 --record=true
# 版本回退
kubectl rollout undo deploy/mynginx --to-revision=1
2.4.6 其他工作负载
Deployment:无状态应用,比如微服务,提供多副本功能
StatefulSet:有状态应用部署,比如redis,提供稳定的存储、网络等功能
DaemonSet:守护型应用部署,比如日志收集组件,在每个机器都运行一份
Job/CronJob:定时任务部署,比如垃圾清理组件,可以在指定时间运行。
2.5 Service
Service是 pod的服务发现与负载均衡
Kubernetes service 定义了一种抽象: 一个pods的逻辑分组,一种可以访问他们的策略 --通常称为微服务,这一组pod能够被service访问到,通常是通过Label Selector
service 能够提供负载均衡的能力,但是在使用上有以下限制。
- 只提供4层负载均衡能力,为没有7层能力,但有时我们可能需要更多的匹配规则来转发请求,这点上4能负载均衡是不支持的。
注意:这里的是默认没有7层,但是后面添加一个ingress来实现
service的类型:
ClusterIP:默认类型,自动分配一个仅仅可以Cluster内部可以访问的虚拟ip
NodePort:在ClusterIp基础上为Service在每台机器上绑定一个端口,这样就可以通过<NodeIP>:NodePort 来访问该服务
LoadBalancer: 在NodePort的基础上,借助cloud provider 创建一个外部负载均衡器,并将请求转发到<NodeIP>:NodePort
ExternalName: 把集群外部的服务引入到集群内部来,在集群内部直接使用,没有任何类型代理被创建,这只有Kubernetes 1.7 或更高版本的kube-dns才支持。
2.5.1 Service 端口暴露
ClusterIP(集群内部访问)
命令行操作
kubectl expose deploy mynginx --port=8000 --target-port=80
shell
➜ ~ kubectl expose deploy mynginx --port=8000 --target-port=80
service/mynginx exposed
➜ ~ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 26h
mynginx ClusterIP 10.106.208.37 <none> 8000/TCP 30s
nginx LoadBalancer 10.104.199.33 <pending> 80:31765/TCP 23h
➜ ~ curl 10.106.208.37:8000
11111
➜ ~ curl 10.106.208.37:8000
333333
➜ ~ curl 10.106.208.37:8000
22222
此命令相当于
kubectl expose deploy mynginx --port=8000 --target-port=80
--type=ClusterIP
--type=ClusterIP:意思为只在集群内部暴露
还可以使用服务名访问:规则 ,服务名.所在名称空间.svc
curl mynginx.defalut.svc:8000
注意:此种方式只能在pod内部使用,在集群终端使用无效
NodePort(集群外部可以访问)
kubectl expose deploy mynginx --port=8000 --target-port=80 --type=NodePort
shell
➜ ~ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 26h
mynginx NodePort 10.108.149.195 <none> 8000:32250/TCP 2s
nginx LoadBalancer 10.104.199.33 <pending> 80:31765/TCP 23h
➜ ~ curl master1.com:32250
333333
➜ ~ curl master1.com:32250
22222
默认暴露的端口区间:30000-32767
2.6 Ingress
概念:Service的统一网关入口
2.6.1 Ingress安装
shell
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.5.1/deploy/static/provider/cloud/deploy.yaml
问题: 安装完成后只能在ingress所处的node能通过ip直接访问,无法通过集群访问
产生原因:
markdown
如果你使用自建的 `Kubernetes` 集群([minikube](https://links.jianshu.com/go?to=https%3A%2F%2Fminikube.sigs.k8s.io%2Fdocs%2Fstart%2F)、[kubeadm](https://links.jianshu.com/go?to=https%3A%2F%2Fkubernetes.io%2Fdocs%2Fsetup%2Fproduction-environment%2Ftools%2Fkubeadm%2Finstall-kubeadm%2F) 等)。
在这种情况下,没有集成 `LoadBalancer`(与 AWS、Google Cloud、阿里云等云厂商不同)。使用此默认设置,你只能使用 `NodePort` 或 `Ingress Controller`。
这时,如果你部署 `LoadBalancer` 则会出现 `External-IP` 一直处于 `pending` 的问题。
解决方案:安装MetalLB
markdown
由于Kubernetes本身并不提供LoadBalaner Ingress Controller, 因此通常使用云平台本身的loadBalancer,如果你是自己在裸机上搭建Kubernetes,需要手动搭建LoadBalancer Ingress Controller
MetalLB Installation
MetalLB安装步骤: 参考网站:https://metallb.universe.tf/installation/
markdown
# Installation
Before starting with installation, make sure you meet all the [requirements](https://metallb.universe.tf/#requirements). In
particular, you should pay attention to [network addon
compatibility](https://metallb.universe.tf/installation/network-addons/).
If you’re trying to run MetalLB on a cloud platform, you should also
look at the [cloud compatibility](https://metallb.universe.tf/installation/clouds/) page and make sure your cloud platform can work with MetalLB
(most cannot).
There are three supported ways to install MetalLB: using plain Kubernetes
manifests, using Kustomize, or using Helm.
## Preparation
If you’re using kube-proxy in IPVS mode, since Kubernetes v1.14.2 you have to enable strict ARP mode.
*Note, you don’t need this if you’re using kube-router as service-proxy because it is enabling strict ARP by default.*
You can achieve this by editing kube-proxy config in current cluster:
bash
kubectl edit configmap -n kube-system kube-proxy
and set:
yaml
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
strictARP: true
Installation by manifest
To install MetalLB, apply the manifest:
bash
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-native.yaml
If you want to deploy MetalLB using the FRR mode, apply the manifests:
bash
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-frr.yaml
Please do note that these manifests deploy MetalLB from the main development branch. We highly encourage cloud operators to deploy a stable released version of MetalLB on production environments!
2.6.2 ingress测试
生成两个deployment实例
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-server
labels:
app: hello-server
spec:
replicas: 3
selector:
matchLabels:
app: hello-server
template:
metadata:
labels:
app: hello-server
spec:
containers:
- name: hello-server
image: nginx:1.14.2
ports:
- containerPort: 9000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-demo
labels:
app: nginx-demo
spec:
replicas: 3
selector:
matchLabels:
app: nginx-demo
template:
metadata:
labels:
app: nginx-demo
spec:
containers:
- name: nginx-demo
image: nginx
---
apiVersion: v1
kind: Service
metadata:
name: nginx-demo
labels:
app: nginx-demo
spec:
selector:
app: nginx-demo
ports:
- port: 8000
protocol: TCP
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: hello-server
labels:
app: hello-server
spec:
selector:
app: hello-server
ports:
- port: 8000
protocol: TCP
targetPort: 9000
配置ingress
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
spec:
ingressClassName: nginx
rules:
- host: "hello.master.com"
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: hello-server
port:
number: 8000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress-nginx
spec:
ingressClassName: nginx
rules:
- host: "nginx.master.com"
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: nginx-demo
port:
number: 8000
最后修改host域名
shell
~ curl hello.master.com:32268/ ✔
helloworld 1111
~ curl hello.master.com:32268/ ✔
helloworld 222222
~ ✔
~ curl nginx.master.com:32268/ INT ✘
nginx demo 222222
~ curl nginx.master.com:32268/ ✔
nginx demo 222222
~ curl nginx.master.com:32268/ ✔
nginx demo 222222
~ curl nginx.master.com:32268/ ✔
nginxdemo 1111
markdown
<注意:注意:>
当参数 path: / 更改匹配规则时,
如改为:path: /admin
此时访问 http://域名:端口/admin
通过ingress后到达pod中nginx的请求路径也是带有参数 /admin 的
注意
ingress高级功能:
具体的参见官方文档:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/
1.路径重写
路径重写重写,解决上面提到的问题
yamlapiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 name: minimal-ingress-nginx spec: ingressClassName: nginx rules: - host: "nginx.master.com" http: paths: - pathType: Prefix path: /something(/|$)(.*) backend: service: name: nginx-demo port: number: 8000
说明
shellIn this ingress definition, any characters captured by (.*) will be assigned to the placeholder $2, which is then used as a parameter in the rewrite-target annotation. For example, the ingress definition above will result in the following rewrites: rewrite.bar.com/something rewrites to rewrite.bar.com/ rewrite.bar.com/something/ rewrites to rewrite.bar.com/ rewrite.bar.com/something/new rewrites to rewrite.bar.com/new
2.流量限制
- 参见官方文档
2.6.3 网络模型
2.7 存储抽象
2.7.1 NFS 安装配置
主节点
shell
# 所有节点安装软件
yum install -y nfs-utils
# 主节点配置
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
mkdir -p /nfs/data
systemctl enable rpcbind --now
systemctl enable nfs-server --now
#配置生效
exportfs -r
从节点:
shell
#检查主节点开放的目录
showmount -e 192.168.2.201
# 建目录
mkdir -p /nfs/data
#挂载
mount -t nfs 192.168.2.201:/nfs/data/ /nfs/data
#测试
touch /nfs/data/test.txt
2.7.2 deployment 原生方式数据挂载
注意: node节点上必须部署nfs从节点,不然无法使用。
(坑)一开始我只在master部署了,导致失败,查了半天
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-pv-demo
labels:
app: nginx-pv-demo
spec:
replicas: 3
selector:
matchLabels:
app: nginx-pv-demo
template:
metadata:
labels:
app: nginx-pv-demo
spec:
containers:
- name: nginx-pv-demo
image: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
nfs:
server: 192.168.2.201
path: /nfs/data/nginx-pv
原生的挂载方式存在以下缺点
删除pod后 在磁盘上的内容无法删除,只能手动删除。
对磁盘资源使用无限制
因此解决方案:\
2.7.4 通过pv&pvc挂载
PV&PVC
Pv:持久卷,将应用需要持久化的数据保存到指定位置
PVC: 持久卷申明,
说明:pv组建一个静态的pv池,pod创建一个pvc(相当于一个访问令牌),pvc根据大小会指定适合的空间来使用。如果pod销毁时删除pvc,那么磁盘上的相应数据也会被删
- 创建步骤:
- 执行此配置文件进行创建pv池
yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv01-10m
spec:
capacity:
storage: 10m
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/01
server: 192.168.2.201
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv02-1g
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/02
server: 192.168.2.201
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv03-3g
spec:
capacity:
storage: 3Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/03
server: 192.168.2.201
创建pvc
yamlapiVersion: v1 kind: PersistentVolumeClaim metadata: name: nginx-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi storageClassName: nfs # 注意:storageClassName和上面创建的pv的storageClassname 名称相同
创建通过pvc创建deployment
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-pvc-demo
labels:
app: nginx-pvc-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx-pvc-demo
template:
metadata:
labels:
app: nginx-pvc-demo
spec:
containers:
- name: nginx-pvc-demo
image: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
persistentVolumeClaim:
claimName: nginx-pvc
## 注意:只有成功建立pvc后才能够成功建立deployment
2.7.5 configMap抽取配置
抽取应用配置,并可以自动更新
1). 创建redis.conf 配置集
kubectl create cm redis-conf --from-file=redis.conf
查看配置集
kubectl get cm
查看配置集内容
kubectl edit cm redis-conf -oyaml
yaml
apiVersion: v1
data:
redis.conf: |
appendonly yes
kind: ConfigMap
metadata:
name: redis-conf
namespace: default
2)redis根据configmap中的配置启动
3) 启动调用逻辑
2.7.6 Secret
Secret对象类型用来保存敏感信息,例如密码 OAuth 令牌和ssh秘钥。将这些信息放在secret中比放在pod更加方便安全。
创建secret命令
shell
kubectl create secret docker-registry \
NAME
--docker-username=user
--docker-password=password
--docker-email=email
[--docker-server=string]
[--from-literal=key1=value1]
[--dry-run]
#例如
kubectl create secret docker-registry \
my-secret \
--docker-server=DOCKER_REGISTRY_SERVER \
--docker-username=DOCKER_USER \
--docker-password=DOCKER_PASSWORD \
--docker-email=DOCKER_EMAIL
使用secret
yaml
apiVersion: v1
kind: pod
metadata:
name: private-nginx
spec:
containers:
- name: private-nginx
image: 仓库镜像路径
imagePullSecrets:
- name: my-secret
2.8 污点
helm
是什么
HeLm是一个Kubernetes应用程序包管理工具,它允许你轻松管理和部署Kubernetes)应用程序。HeLm通过使用称为Charts的预定义模板来简化 Kubernetes/应用程序的部署和管理。Chart包含了一组Kubernetes对象定义,可以描述一个应用程序的完整部署和资源需求,包括Deployment、 Service、ConfigMap、Secret等。使用Helm,你可以轻松地安装、升级、卸载和回滚Kubernetes应用程序。 同时,HeLm还提供了一些便捷的功能,如依赖管理、全局变量、条件渲染等,可以帮助你更好地管理应用程序的部署。HeLm有两个主要的组件:HeLm客户端 (helm)和Helm服务器(Tiller).Helm客户端可以在本地运行,而Tiller则运行在Kubernetes:集群中,并负责将Charts转换为Kubernetes对象。
安装
概念
==chart== Chart 代表着 Helm 包。它包含在 Kubernetes 集群内部运行应用程序,工具或服务所需的所有资源定义。你可以把它看作是 Homebrew formula,Apt dpkg,或 Yum RPM 在Kubernetes 中的等价物
==_Repository== Repository(仓库) 是用来存放和共享 charts 的地方。它就像 Perl 的 CPAN 档案库网络 或是 Fedora 的 软件包仓库,只不过它是供 Kubernetes 包所使用的。
==Release== Release 是运行在 Kubernetes 集群中的 chart 的实例。一个 chart 通常可以在同一个集群中安装多次。每一次安装都会创建一个新的 release。以 MySQL chart为例,如果你想在你的集群中运行两个数据库,你可以安装该chart两次。每一个数据库都会拥有它自己的 release 和 release name。
3. kubeSphere
3.1 kubeSphere 安装
3.1.1 环境准备
环境准备
主节点:
master1 master2 master3
从节点:
node1 node2 node3
配置:
内存:4G
cpu: 2核心 (i7-12700)
硬盘:20G
3.1.2 版本选择
软件版本选择: KubeSphere: V3.3.1
kubernetes : v1.21.14 kuberSphere版本要求:
markdown
您的 Kubernetes 版本必须为:v1.19.x、v1.20.x、v1.21.x、* v1.22.x、* v1.23.x 和 * v1.24.x。带星号的版本可能出现边缘节点部分功能不可用的情况。因此,如需使用边缘节点,推荐安装 v1.21.x 及之前的版本
- docker版本:
- 根据k8s的官方文档要求选择版本
- 要求查看位置:github代码界面》CHANGELOG》
3.1.3 安装docker
官方参考文档:Install Docker Engine on CentOS | Docker Documentation
shell
# 卸载旧版本
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 添加仓库
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
#查看版本
yum list docker-ce --showduplicates | sort -r
#安装指定版本
sudo yum install docker-ce-20.10.2-3.el7 docker-ce-cli-20.10.2-3.el7 containerd.io docker-compose-plugin
#设置开机自启并启动
sudo systemctl enable docker --now
#测试
sudo docker run hello-world
#配置docker cgroup驱动,在/etc/docker/daemon.json 添加
#{
#"exec-opts": ["native.cgroupdriver=systemd"]
#}
cat >> /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
#重启服务
systemctl restart docker
#查看是否成功
docker info | grep Cgroup
注意:
docker 被墙了,所以必须翻墙才可以成功安装,但是在终端配置export 无法访问,必须按照如下配置。
mkdir -p /etc/systemd/system/docker.service.d vim /etc/systemd/system/docker.service.d/proxy.conf
把此内容放到proxy.conf中,docker就可以通过代理访问了。(巨坑,fuck GFW)
shell
[Service]
Environment="HTTP_PROXY=http://192.168.137.1:10809/"
Environment="HTTPS_PROXY=http://192.168.137.1:10809/"
Environment="NO_PROXY=localhost,127.0.0.1,.example.com"
3.1.4 安装kubernetes
1. 前置准备:
关闭swap
swapoff -a
把/etc/fstab 中的swap注释掉
配置host
shell
cat >> /etc/hosts <<EOF
192.168.2.201 master1.com
192.168.2.202 master2.com
192.168.2.203 master3.com
192.168.2.204 node1.com
192.168.2.205 node2.com
192.168.2.206 node3.com
EOF
- 设置hostname
shell
关闭SELinux
shell#查看状态 getenforce #或者 /usr/sbin/sestatus -v # 将 SELinux 设置为 permissive 模式(相当于将其禁用) sudo setenforce 0 sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
* 关闭防火墙
> 关闭防火墙
>
> systemctl stop firewalld
>
> 禁止开机自启
>
> systemctl disable firewalld
* 转发ipv4 并让iptables看到桥接流量
```shell
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 设置所需的 sysctl 参数,参数在重新启动后保持不变
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# 应用 sysctl 参数而不重新启动
sudo sysctl --system
安装cir-dockerd (kubernetes 1.24后需要安装,1.24去除了内置dockershim )
如果版本大于等于1.24需要安装
https://github.com/Mirantis/cri-dockerd
从github下载下来相应版本安装即可。
注意:安装完成后设置开机自启并启动。 systemctl enable --now cri-docker
2. 安装k8s
安装kubeadm
shell
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF
sudo yum install -y kubelet-1.21.14 kubeadm-1.21.14 kubectl-1.21.14 --disableexcludes=kubernetes
sudo systemctl enable --now kubelet
初始化 admin init
shell
#集群初始化
kubeadm init \
--apiserver-advertise-address=192.168.2.201 \
--control-plane-endpoint="master1.com" \
--kubernetes-version=v1.21.14 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.96.0.0/16 \
--upload-certs
##--token-ttl duration 默认值:24h0m0s
##令牌被自动删除之前的持续时间(例如 1 s,2 m,3 h)。
##如果设置为 '0',则令牌将永不过期
--apiserver-advertise-address string
The IP address the API Server will advertise it's listening on. If not set the default network interface will be used.
--upload-certs
Upload control-plane certificates to the kubeadm-certs Secret.
flannel安装卸载
flannel 网络卸载: 由于想换成calico,但是已经安装了flannel,所以进行卸载
shell
#第一步,在master节点删除flannel
kubectl delete -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
#第二步,在node节点清理flannel网络留下的文件
ifconfig cni0 down
ip link delete cni0
ifconfig flannel.1 down
ip link delete flannel.1
rm -rf /var/lib/cni/
rm -f /etc/cni/net.d/*
3. calico安装
4. NFS安装配置
a) 安装NFS
由于kubesphere需要默认存储类型,需要自己安装,这里使用nfs作为默认存储。
但是nfs需要设置成动态供应,上面有讲述静态供应配置。
主节点
shell
# 所有节点安装软件
yum install -y nfs-utils
# 主节点配置
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
mkdir -p /nfs/data
systemctl enable rpcbind --now
systemctl enable nfs-server --now
#配置生效
exportfs -r
从节点:
注意:这里的从节点指的是所有node节点
shell
#检查主节点开放的目录
showmount -e 192.168.2.201
# 建目录
mkdir -p /nfs/data
#挂载
mount -t nfs 192.168.2.201:/nfs/data/ /nfs/data
#测试
touch /nfs/data/test.txt
b) 配置nfs默认存储
注意:这里所有的master节点都要更改
markdown
注意:k8s 1.21版本中创建pvc时nfs-provisioner会报错
E0903 08:00:24.858523 1 controller.go:1004] provision “default/test-claim” class “managed-nfs-storage”: unexpected error getting claim reference: selfLink was empty, can’t make reference
解决方法:
修改 /etc/kubernetes/manifests/kube-apiserver.yaml文件
增加 - --feature-gates=RemoveSelfLink=false
spec:
containers:
- command:
- kube-apiserver
- --feature-gates=RemoveSelfLink=false # 增加这行
- --advertise-address=172.24.0.5
- --allow-privileged=true
- --authorization-mode=Node,RBAC
- --client-ca-file=/etc/kubernetes/pki/ca.crt
... 省略剩余部分 ...
————————————————
版权声明:本文为CSDN博主「简单生活FF」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/gxf1027/article/details/120063398
架构图
由于kubesphere需要默认存储,这里把nfs配置成动态供应作为默认存储。
NFS作为默认存储的动态供应方式
创建nfs-provisioner.yaml文件,
nfs-client-provisioner 是一个 Kubernetes 的简易 NFS 的外部 provisioner,本身不提供 NFS,需要现有的 NFS 服务器提供存储。 注意:地址和目录要改成实际的NFS服务对应配置
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default #与RBAC文件中的namespace保持一致
spec:
replicas: 1
selector:
matchLabels:
app: nfs-client-provisioner
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: nfs-storage #provisioner名称,请确保该名称与 nfs-StorageClass.yaml文件中的provisioner名称保持一致
- name: NFS_SERVER
value: 192.168.2.201 #NFS Server IP地址
- name: NFS_PATH
value: /nfs/data #NFS挂载卷
volumes:
- name: nfs-client-root
nfs:
server: 192.168.2.201 #NFS Server IP地址
path: /nfs/data #NFS 挂载卷
创建nfs-StorageClass.yaml文件
StorageClass是对存储资源的抽象定义,对用户设置的PVC申请屏蔽后端存储的细节,减轻管理员手工管理PV的工作,由系统自动完成PV的创建和绑定,实现动态资源供给。 StorageClass的定义主要包括名称、后端存储的提供者(provisioner)和后端存储对应的参数。对于后端NFS存储来说,配置相对简单,只需要指定provisioner即可。
yaml
# nfs-StorageClass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storage
annotations:
storageclass.kubernetes.io/is-default-class: "true" #作为default中默认的sc
provisioner: nfs-storage #这里的名称要和provisioner配置文件中的环境变量PROVISIONER_NAME保持一致
reclaimPolicy: Delete # 默认为delete
parameters:
archiveOnDelete: "true" # false表示pv被删除时,在nfs下面对应的文件夹也会被删除,true正相反
创建rbac.yaml
以下开始部署nfs-provisioner 注意:本次测试都部署在default namespace下,如果需要部署到其他的ns,需要修改yaml文件中namespace。 (1)创建ServiceAccount、ClusterRole、ClusterRoleBinding等,为nfs-client-provisioner授权
yaml
# rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
`
创建测试
#创建pve
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nfs-pvc
annotations:
volume.beta.kubernetes.io/storage-class: "nfs-storage"
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
---
# 创建deployment