k8s部署搭建参考:基于Linux(Ubuntu20.04)初步搭建k8s集群
实践是检验真理的唯一标准,只有从实践中才能快速熟悉理解k8s。
三个基本概念,Pod,Service,Namespace。
Pod:k8s最小单元,pod和容器的区别,容器包含在pod中,一个pod中有一个pause容器和若干个业务容器,而容器就是单独的一个容器,简而言之,pod是一组容器,而容器单指一个容器。
Service:pod每次动态创建后,自动分配的ip会不同,所以引入了service(即服务的注册与发现),通俗的讲,就是管理上网功能的,相关于网络管理员,保证网络正常就行。
namespace:命名空间,主要用于隔离
k8s一切皆容器,所有的服务也好,插件也好,都是运行在docker容器之中。
部署项目,类似docker-compose通过yaml文件拉取生成项目布置,docker-compose只能单机本机上部署,但k8s可以集群部署多台服务器,即node节点。
环境介绍:
k8s-master:Ubuntu–192.168.152.100
k8s-node01:Ubuntu–192.168.152.101
k8s-node02:Ubuntu–192.168.152.102
布置之前,先完善kubectl 命令自动补全,因为默认kubectl按快捷键没有补齐的。
#安装bash-completion(如果已经安装忽略即可):
sudo apt install bash-completion
#测试一下:
source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)
#测试没问题后,对 /root/.bashrc 加2行代码 ,方便以后每次登录自动生效:
source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)
在yaml文件中,有个kind参数,用来指定创建资源的角色/类型。
正常创建是创建Deployment和Service两个 yaml文件,及kind分别是deployment,Service来搭建。
这里可以直接创建pod 测试来熟悉k8s相关操作。而且只能单个创建pod,无法达到集群的要求。
一般不直接kind: Pod创建pod,而是通过controller来创建pod。deployment为其中一种controller。这里先演示测试最基本的搭建,所以设置为kind:Pod
#编辑
sudo vim nginx_pod.yaml
内容如下,相关参数说明见本文最后。
apiVersion: v1 #核心,对象pod、service等
kind: Pod
metadata: #资源的元数据/属性
name: nginx
labels:
app: nginx
spec: #设置该资源的内容
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80 #容器端口
hostPort: 8081 #让外部访问端口,官方及其不推荐这种方式,走的防火墙iptables方式,本人测试没成功,仍然无法从外部访问。
yaml创建完成后,使用命令 kubectl apply
或者kubectl create
加入k8s并创建 pod
两者命令区别:
kubectl create
:是先删除所有现有的东西,重新根据yaml文件生成新的。无法覆盖,报错。
kubectl apply
:根据配置文件里面列出来的内容,升级现有的,直接覆盖原来的。(建议使用)
kubectl apply -f nginx_pod.yaml
#或者用以下命令
kubectl create -f nginx_pod.yaml
创建完成后,可查看pod 的状态,执行命令:
kubectl get pods -o wide # 列出所有 pod 并显示详细信息
kubectl get pods nginx -o wide # 列出所有nginx pod 并显示详细信息
显示如下,可以看到 nginx pod 已处于 Running 状态,表示刚创建的 pod 已成功运行起来。
ubuntu@k8s-master:~$ kubectl apply -f nginx_pod.yaml
pod/nginx created
ubuntu@k8s-master:~$ kubectl get pods nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 35s 172.16.58.193 k8s-node02 <none> <none>
通过查看pods状态,可以得到信息,pods的内部IP为172.16.58.193,master已将nginx自动部署至node02节点(如没有特殊设置,k8s会通过服务器负载均衡自动布置合适的node节点上)。
在node2节点的机器上,查看docker可以看到,docker nginx已经运行。
在master主节点上,同样可用类似docker exec的命令,进入容器查看状态。
#进入容器
kubectl exec -it nginx -- /bin/sh
#进入容器后,执行命令访问nginx。可正常返回nginx页面。
curl localhost
测试完成后,可以用以下命令删除此pod
kubectl delete -f nginx_pod.yaml
通过测试可以看出,使用hostPort的方式,这种很难通过外网访问内部容器。
所以通过其他方式访问,最常用的是NodePort的方式,对比这两种方式:
1、使用hostPort的方式,这种还会占用其他宿主机的端口,同时会引发其他错误,官方也不推荐。
2、使用NodePort的方式,k8s广泛应用的服务暴露方式,普遍运用的方式,这种也是Service默认的网络端口模式。
接下来用Deployment和Service正常创建多个pod。
通过deployment创建Pod,创建deployment yaml文件
sudo vim nginx-dep.yml
内容为
apiVersion: apps/v1 #Deployment用这个
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector: #标签选择器,与metadata中的labels:标签共同作用,目前不需要理解
matchLabels: #选择包含标签app:nginx的资源
app: nginx
replicas: 3 # 镜像副本数量
template: #这是选择或创建的Pod的模板
metadata: #Pod的元数据
labels: #Pod的标签,上面的selector即选择包含标签app:nginx的Pod
app: nginx
spec: #即在pod中部署功能
containers: #以下容器内容
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
完成后,加入k8s创建pod
kubectl apply -f nginx-dep.yaml
查看pod
kubectl get deploy -o wide
可以看到,3个pod创建完成,分别分布在两个node节点机器上。
ubuntu@k8s-master:~$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-585449566-547fh 1/1 Running 0 78s 172.16.85.193 k8s-node01 <none> <none>
nginx-deployment-585449566-pjs7n 1/1 Running 0 78s 172.16.58.195 k8s-node02 <none> <none>
nginx-deployment-585449566-txzvf 1/1 Running 0 78s 172.16.58.196 k8s-node02 <none> <none>
创建Service yaml文件
sudo vim nginx-service.yaml
内容为
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30080 #端口范围只能是 30000-32767,外部通过此端口访问
type: NodePort #nodePort方式,必须声明这类型
完成后,加入k8s创建
kubectl create -f nginx-service.yaml
此时需要用kubectl get svc查看服务了,而不是查看pod。
kubectl get svc -o wide
查看如下已正常启动
ubuntu@k8s-master:~$ kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 25h <none>
nginx-service NodePort 10.101.18.212 <none> 80:30080/TCP 106s app=nginx
在浏览器输入节点IP:30080访问
master主节点IP访问测试:
master节点IP访问测试:
测试完成,这时候正式nginx集群搭建完成。
命名空间适用于存在很多跨多个团队或项目的用户的场景。对于只有几到几十个用户的集群,根本不需要创建或考虑命名空间。当需要名称空间提供的功能时,请开始使用它们。
简单理解,不同团队之间的项目,隔离作用,互不干扰。但是必要情况下,也是可以互相通信的。
Kubernetes中的集群默认会有一个叫default的namespace。实际上,应该是3个:
命令kubectl get ns
可查看命名空间。
ubuntu@k8s-master:~$ kubectl get ns
NAME STATUS AGE
default Active 42h
kube-node-lease Active 42h
kube-public Active 42h
kube-system Active 42h
所有没有指定namespace下,集群都默认在default 命名空间。
两种方式:命令和yaml文件
1)命令:kubectl create namespace test
2)使用yaml文件:
sudo vim namespace.yaml
kind: Namespace
apiVersion: v1
metadata:
name: test
labels:
name: test
然后,执行kubectl apply -f namespace.yaml
也有两种方式:
1)命令最后指定命名空间:kubectl apply -f pod.yaml --namespace=test
2)在yaml文件指定:
apiVersion: v1
kind: Pod
metadata:
name: mypod
namespace: test #指定命名空间
labels:
name: mypod
spec:
containers:
- name: mypod
image: nginx
一旦指定命名空间后,在查看Pod或者Service,也必须指定命名空间,否则查看不到,因为没指定之前,所有命令默认是default的命名空间。
查看test命名空间的pod
kubectl get pods --namespace=test
如上所示,所有命令默认是default的命名空间,所有用其他命名空间,必须指定命令。所以可以切换至命名空间,就不需要在命令后指定了。
所以需要用到插件kubens,插件地址:https://github.com/ahmetb/kubectx#manual-installation-macos-and-linux
这里面包含两个插件,需要的话都可以安装。下载安装:
sudo git clone https://github.com/ahmetb/kubectx /opt/kubectx
sudo ln -s /opt/kubectx/kubectx /usr/local/bin/kubectx
sudo ln -s /opt/kubectx/kubens /usr/local/bin/kubens
安装完成,当你运行kubens
命令,它会高亮当前的namespace,
切换test空间,kubens test
,再次查看所在空间,已切换完成,查看test所在空间的资源,输入命令也无需在次指定test的命名空间。
apiVersion: v1 #指定api版本,此值必须在kubectl apiversion,命令kubectl api-versions可查看
kind: Pod #指定创建资源的角色/类型
metadata: #资源的元数据/属性
name: django-pod #资源的名字,在同一个namespace中必须唯一
labels: #设定资源的标签,使这个标签在service网络中备案,以便被获知
k8s-app: django
version: v1
kubernetes.io/cluster-service: "true"
annotations: #设置自定义注解列表
- name: String #设置自定义注解名字
spec: #设置该资源的内容
restartPolicy: Always #表示自动重启,一直都会有这个容器运行
nodeSelector: #选择node节点14 zone: node1
containers:
- name: django-pod #容器的名字
image: django:v1.1 #容器使用的镜像地址
imagePullPolicy: Never #三个选择Always、Never、IfNotPresent,每次启动时检查和更新(从registery)images的策略,
# Always,每次都检查
# Never,每次都不检查(不管本地是否有)
# IfNotPresent,如果本地有就不检查,如果没有就拉取
command: ['sh'] #启动容器的运行命令,将覆盖容器中的Entrypoint,对应Dockefile中的ENTRYPOINT
args: ["$(str)"] #启动容器的命令参数,对应Dockerfile中CMD参数
env: #指定容器中的环境变量
- name: str #变量的名字
value: "/etc/run.sh" #变量的值
resources: #资源管理
requests: #容器运行时,最低资源需求,也就是说最少需要多少资源容器才能正常运行
cpu: 0.1 #CPU资源(核数),两种方式,浮点数或者是整数+m,0.1=100m,最少值为0.001核(1m)
memory: 32Mi #内存使用量
limits: #资源限制
cpu: 0.5
memory: 32Mi
ports:
- containerPort: 8080 #容器开发对外的端口
name: uwsgi #名称
protocol: TCP
livenessProbe: #pod内容器健康检查的设置
httpGet: #通过httpget检查健康,返回200-399之间,则认为容器正常
path: / #URI地址
port: 8080
#host: 127.0.0.1 #主机地址
scheme: HTTP
initialDelaySeconds: 180 #表明第一次检测在容器启动后多长时间后开始
timeoutSeconds: 5 #检测的超时时间
periodSeconds: 15 #检查间隔时间
#也可以用这种方法
#exec: 执行命令的方法进行监测,如果其退出码不为0,则认为容器正常
# command:
# - cat
# - /tmp/health
#也可以用这种方法
#tcpSocket: //通过tcpSocket检查健康
# port: number
lifecycle: #生命周期管理(钩子)
postStart: #容器运行之前运行的任务
exec:
command:
- 'sh'
- 'yum upgrade -y'
preStop: #容器关闭之前运行的任务
exec:
command: ['service httpd stop']
volumeMounts: #挂载设置
- name: volume #挂载设备的名字,与volumes[*].name 需要对应
mountPath: /data #挂载到容器的某个路径下
readOnly: True
volumes: #定义一组挂载设备
- name: volume #定义一个挂载设备的名字
#meptyDir: {}
hostPath:
path: /opt #挂载设备类型为hostPath,路径为宿主机下的/opt