集群方案
使用三台物理机或VMwareVMware虚拟机来搭建集群环境,一台主控服务器,两台工作节点服务器。
一,集群安装准备
kubeasz项目https://github.com/easzlab/kubeasz)极大的简化了k8s集群的安装过程,他提供的工具可以轻松安装和管理k8s集群。
主控服务器
先准备主控服务器192.168.111.191
调整 VMware 虚拟机虚拟机的内存和 cpu:
下载离线文件,安装DockerDocker
在主控服务器上下载安装环境初始化脚本工具 ezdown
:
export release=3.1.0curl -C- -fLO --retry 3 https://github.com/easzlab/kubeasz/releases/download/${release}/ezdownchmod +x ./ezdownls -l
使用工具脚本下载离线文件,并安装Docker
默认下载最新推荐k8s/docker等版本(更多关于ezdown的参数,运行./ezdown 查看)
./ezdown -D
这里使用离线方式安装
D:\Storages\Study\SpringCloud2\亿发课前资料-2102\DevOps课前资料\kubernetes\kubeasz-3.1.0\ezdown
D:\Storages\Study\SpringCloud2\亿发课前资料-2102\DevOps课前资料\kubernetes\images.gz
这2个文件 上传到 /root 目录下
D:\Storages\Study\SpringCloud2\亿发课前资料-2102\DevOps课前资料\kubernetes\kubeasz-3.1.0\kubeasz
这个kubeasz目录 上传到 /etc 目录下
cd ~
chmod +x ezdown
一键安装,如果已经安装,会提示我们通过离线的方式上传到/etc目录下了)
./ezdown -D
导入 docker 镜像,后面使用这些镜像用来测试 k8s:
docker load -i images.gzdocker images
可选下载离线系统包 适用于无法使用yum/apt仓库情形),这里我们不需要执行这个。
./ezdown -P
上述脚本运行成功后,所有文件(kubeasz代码、二进制、离线镜像)均已整理好放入目录/etc/kubeasz
/etc/kubeasz 包含 kubeasz 版本为 ${release} 的发布代码
/etc/kubeasz/bin 包含 k8s/etcd/docker/cni 等二进制文件
/etc/kubeasz/down 包含集群安装时需要的离线容器镜像
/etc/kubeasz/down/packages 包含集群安装时需要的系统基础软件
主控服务器 需要安装 python、pip、ansible
ansible
是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。
kubeasz 使用 ansible
来自动安装配置集群,所以这里先要安装 ansible
。
yum install python -ycurl -O https://bootstrap.pypa.io/pip/2.7/get-pip.pypython get-pip.pypython -m pip install --upgrade "pip < 21.0"pip install ansible -i https://mirrors.aliyun.com/pypi/simple/
工作节点
在工作节点服务器上重复以上所有操作。
如果使用 VMware 虚拟机,只需要从第一台服务器克隆即可。
192.168.111.192 、 192.168.111.193
二,配置集群安装环境
启动 kubeasz 容器,这个容器用来帮我们安装的
./ezdown -S
设置参数允许离线安装
sed -i 's/^INSTALL_SOURCE.*$/INSTALL_SOURCE: "offline"/g' /etc/kubeasz/example/config.yml
配置免密登录其他服务器,这是能控制别人服务器的基础
主控服务器191)生成密钥对,将公钥发送到所有工作服务器192/193)
#这一步不用执行,一般服务器都已经生成好了的
ssh-keygen -t rsa -b 2048 -N '' -f ~/.ssh/id_rsa#以下在主控服务器191上执行
ssh-copy-id 192.168.111.191
ssh-copy-id 192.168.111.192
ssh-copy-id 192.168.111.193
这一步是将主控服务器的公钥 id_rsa.pub 追加到所有服务器包括自己)的 ~/.ssh/authorized_keys 文件中
创建集群配置
cd /etc/kubeaszchmod +x ezctl./ezctl new cs1
配置服务器地址
vi /etc/kubeasz/clusters/cs1/hosts
etcd注册中心只能是基数,好选举)
kube_master主控服务器地址
kube_node工作服务器地址
执行一键安装
执行安装前,3台服务器拍个快照。安装错误好回退。
cd /etc/kubeasz#这个过程要执行很久
./ezctl setup cs1 all
kube-proxy 启动失败
kubeasz问题-FAILED – RETRYING: 轮询等待node达到Ready状态_哪有天生的学霸,一切都是厚积薄发的博客-CSDN博客
[root@centos00 kubeasz]# docker info|grep DriverStorage Driver: overlay2Logging Driver: json-fileCgroup Driver: cgroupfs
docker中将资源管理驱动设置统一:
“exec-opts”: [“native.cgroupdriver=systemd”]
vi /etc/docker/daemon.json
{"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn","http://hub-mirror.c.163.com"],"max-concurrent-downloads": 10,"log-driver": "json-file","log-level": "warn","log-opts": {"max-size": "10m","max-file": "3"},"data-root": "/var/lib/docker","exec-opts": ["native.cgroupdriver=systemd"]
}
重启docker
systemctl daemon-reload
systemctl restart docker
[root@centos00 kubeasz]# docker info|grep DriverStorage Driver: overlay2Logging Driver: json-fileCgroup Driver: systemd
查看k8s运行状态
systemctl status kubelet
查看K8S运行日志
journalctl -xefu kubelet
重新执行
cd /etc/kubeasz#这个过程要执行很久
./ezctl setup cs1 all
设置 kubectl 命令的别名
# 设置 kubectl 命令别名 k
echo "alias k='kubectl'" >> ~/.bashrc# 使设置生效
source ~/.bashrc
查看集群信息
[root@centos00 ~]# k get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-0 Healthy {"health":"true"}
etcd-2 Healthy {"health":"true"}
etcd-1 Healthy {"health":"true"}
查看节点信息
[root@centos00 ~]# k get no
NAME STATUS ROLES AGE VERSION
192.168.111.191 Ready,SchedulingDisabled master 5h20m v1.21.0
192.168.111.192 Ready node 4h35m v1.21.0
192.168.111.193 Ready node 4h35m v1.21.0
初步尝试 kubernetes
kubectl run 命令是最简单的部署引用的方式,它自动创建必要组件,这样,我们就先不必深入了解每个组件的结构
概念
Pod(豌豆荚,这个名字很形象,里面的容器代表一个个docker容器)
k8s 对Docker容器的封装对象。pod一般里面只有一个容器,后面可以简单的直接将pod理解为一个docker容器。
解耦,pod里面可以不是docker容器,还可以是其他容器。pod可以贴标签。
控制器RC)
自动控制容器部署的工具
容器自动伸缩
可以添加标签,也可以给启动的容器贴标签,
控制器种类:ReplicationController、ReplicaSet、DaemonSet、Job、Cronjob
Service类似网关的路由转发功能)
通过前面的docker学习,我们知道要访问一个容器,需要将容器的端口映射到宿主机,当容器经常改变伸缩),不可能每个容器都映射一个宿主机的端口,这时就使用Service来转发。
不变的访问地址
pod(容器),可以独立存在,也可以在控制器RC)下。当rc的标签和pod标签不一致标签被修改) ,pod就会脱离rc,成为一个独立的容器。
控制器创建容器,Service访问容器
使用 ReplicationController 和 pod 部署应用
Pod是用来封装Docker容器的对象,它具有自己的虚拟环境端口, 环境变量等),一个Pod可以封装多个Docker容器.
RC是用来自动控制Pod部署的工具,它可以自动启停Pod,对Pod进行自动伸缩.
下面我们用命令部署一个RC
控制器
ReplicationController
RC可以自动化维护多个pod,只需指定pod副本的数量,就可以轻松实现自动扩容缩容
当一个pod宕机,RC可以自动关闭pod,并启动一个新的pod替代它
下面是一个RC的部署文件,设置启动三个kubia容器:
cd ~cat <<EOF > kubia-rc.yml
apiVersion: v1
kind: ReplicationController # 资源类型
metadata: name: kubia # 为RC命名
spec:replicas: 3 # pod副本的数量selector: # 选择器,用来选择RC管理的podapp: kubia # 选择标签'app=kubia'的pod,由当前RC进行管理template: # pod模板,用来创建新的podmetadata:labels:app: kubia # 指定pod的标签spec:containers: # 容器配置- name: kubia # 容器名image: luksa/kubia # 镜像imagePullPolicy: Neverports:- containerPort: 8080 # 容器暴露的端口
EOF
创建RC
RC创建后,会根据指定的pod数量3,自动创建3个pod
#创建一个控制器
k create -f kubia-rc.yml#查看控制器
k get rc
----------------------------------------
NAME DESIRED想要的容器数量) CURRENT当前容器数量) READY已经就绪容器数量) AGE
kubia 3 3 2 2m11s#查看po的数量
k get po -o wide
------------------------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubia-4gj44 1/1 Running 0 2m33s 172.20.1.4 192.168.111.192 <none> <none>
kubia-nnm98 1/1 Running 0 2m33s 172.20.2.4 192.168.111.193 <none> <none>
kubia-w5l4f 1/1 Running 0 2m33s 172.20.2.5 192.168.111.193 <none> <none>
pod自动伸缩
k8s对应用部署节点的自动伸缩能力非常强,只需要指定需要运行多少个pod,k8s就可以完成pod的自动伸缩
# 将pod数量增加到4个
k scale rc kubia --replicas=4#查看po的数量
k get po -o wide
----------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubia-4gj44 1/1 Running 0 8m25s 172.20.1.4 192.168.111.192 <none> <none>
kubia-nnm98 1/1 Running 0 8m25s 172.20.2.4 192.168.111.193 <none> <none>
kubia-pmbjf 1/1 Running 0 7s 172.20.1.5 192.168.111.192 <none> <none>
kubia-w5l4f 1/1 Running 0 8m25s 172.20.2.5 192.168.111.193 <none> <none># 将pod数量减少到1个
k scale rc kubia --replicas=1# k8s会自动停止两个pod,最终pod列表中会只有一个pod
k get po -o wide
---------------------------------------------------------------------------------------------------------------------
[root@centos00 ~]# k get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubia-4gj44 1/1 Running 0 10m 172.20.1.4 192.168.111.192 <none> <none>
使用 service 对外暴露 pod
#创建暴露)一个service
k expose \rc kubia \--type=NodePort \--name kubia-httpk get svc
------------------------------------------------------------------------------
NAME TYPE CLUSTER-IP EXTERNAL-IP PORTS) AGE
kubia-http NodePort 10.68.221.179 <none> 8080:31467/TCP 6s
上面创建 service 的宿主机端口 31467
访问这个service 地址 curl http://192.168.111.191:31467
发现轮询返回容器。
pod
使用部署文件手动部署pod
创建kubia-manual.yml
部署文件
cd ~
cat <<EOF > kubia-manual.yml
apiVersion: v1 # k8s api版本
kind: Pod # 该部署文件用来创建pod资源
metadata: name: kubia-manual # pod名称前缀,后面会追加随机字符串
spec:containers: # 对pod中容器的配置- image: luksa/kubia # 镜像名imagePullPolicy: Never # 不联网下载镜像name: kubia # 容器名ports:- containerPort: 8080 # 容器暴露的端口protocol: TCP
EOF
使用部署文件创建pod
#手动创建pod容器
k create -f kubia-manual.yml#查看pod容器
k get po -o wide
-----------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubia-manual 1/1 Running 0 114s 172.20.2.8 192.168.111.193 <none> <none>#去192.168.111.193查看,因为已经设置免密登录了,ssh可以直接登录
ssh 192.168.111.193[root@centos00 ~]# docker ps |grep kubia-manual
3982ce118ce8 52eefa1f1af5 "node app.js" 6 minutes ago Up 6 minutes k8s_kubia_kubia-manual_default_f5cd80ab-2869-4bbe-b77e-4c89fae224e7_0
2fcfdc35a543 easzlab/pause-amd64:3.4.1 "/pause" 6 minutes ago Up 6 minutes k8s_POD_kubia-manual_default_f5cd80ab-2869-4bbe-b77e-4c89fae224e7_0
查看pod的部署文件
# 查看pod的部署文件
k get po kubia-manual -o yaml
pod端口转发
临时用来测试这个容器,调式好后一般要关闭,使用service对外提供服务。
使用 kubectl port-forward 命令设置端口转发,对外暴露pod.
使用服务器的 8888 端口,映射到 pod 的 8080 端口
#转发192.168.111.192的8080端口
k port-forward kubia-manual --address localhost,192.168.111.192 8888:8080# 或在所有网卡上暴露8888端口
k port-forward kubia-manual --address 0.0.0.0 8888:8080
在浏览器中访问 http://192.168.111.192:8888/
pod 标签
可以为 pod 指定标签,通过标签可以对 pod 进行分组管理
ReplicationController,ReplicationSet,Service中,都可以通过 Label 来分组管理 pod
创建pod时指定标签
通过kubia-manual-with-labels.yml
部署文件部署pod
在部署文件中为pod设置了两个自定义标签:creation_method
和env
cd ~
cat <<EOF > kubia-manual-with-labels.yml
apiVersion: v1 # api版本
kind: Pod # 部署的资源类型
metadata:name: kubia-manual-v2 # pod名labels: # 标签设置,键值对形式creation_method: manual env: prod
spec:containers: # 容器设置- image: luksa/kubia # 镜像name: kubia # 容器命名imagePullPolicy: Neverports: # 容器暴露的端口- containerPort: 8080protocol: TCP
EOF
使用部署文件创建资源
k create -f kubia-manual-with-labels.yml
查看pod的标签
列出所有的pod,并显示pod的标签
k get po --show-labels
------------------------------------------------------------
NAME READY STATUS RESTARTS AGE LABELS
kubia-5rz9h 1/1 Running 0 109s run=kubia
kubia-manual 1/1 Running 0 52s <none>
kubia-manual-v2 1/1 Running 0 22s creation_method=manual,env=prod
修改pod的标签
pod kubia-manual-v2
的env标签值是prod
, 我们把这个标签的值修改为 debug
修改一个标签的值时,必须指定 --overwrite
参数,目的是防止误修改
k label po kubia-manual-v2 env=debug --overwritek get po -L creation_method,env
---------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE CREATION_METHOD ENV
kubia-5rz9h 1/1 Running 0 15m
kubia-manual 1/1 Running 0 14m
kubia-manual-v2 1/1 Running 0 13m manual debug
为pod kubia-manual
设置标签
k label po kubia-manual creation_method=manual env=debug
为pod kubia-5rz9h
设置标签
k label po kubia-5rz9h env=debug
查看标签设置的结果
k get po -L creation_method,env
--------------------------------------------------------------------------
AME READY STATUS RESTARTS AGE CREATION_METHOD ENV
kubia-5rz9h 1/1 Running 0 18m debug
kubia-manual 1/1 Running 0 17m manual debug
kubia-manual-v2 1/1 Running 0 16m manual debug
使用标签来查询 pod
查询 creation_method=manual
的pod
-l 后面跟查询条件
# -l 查询
k get po \-l creation_method=manual \-L creation_method,env
---------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE CREATION_METHOD ENV
kubia-manual 1/1 Running 0 28m manual debug
kubia-manual-v2 1/1 Running 0 27m manual debug
查询有 env 标签的 pod
# -l 查询
k get po \-l env \-L creation_method,env
---------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE CREATION_METHOD ENV
kubia-5rz9h 1/1 Running 0 31m debug
kubia-manual 1/1 Running 0 30m manual debug
kubia-manual-v2 1/1 Running 0 29m manual debug
组合查询,同时满足creation_method=manual和env=debug
k get po -l creation_method=manual,env=debug --show-labels
NAME READY STATUS RESTARTS AGE LABELS
kubia-manual 1/1 Running 0 66m creation_method=manual,env=debug
kubia-manual-v2 1/1 Running 0 39m creation_method=manual,env=debug
查询不存在 creation_method 标签的 pod
使用!表示不等于
# -l 查询
k get po \-l '!creation_method' \-L creation_method,env
-----------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE CREATION_METHOD ENV
kubia-5rz9h 1/1 Running 0 36m debug
删除容器的一个env标签
k get po --show-labels
NAME READY STATUS RESTARTS AGE LABELS
kubia-4gj44 1/1 Running 0 104m app=kubia,env=debug#删除 env 标签
kubectl label po kubia-4gj44 env-k get po --show-labels
NAME READY STATUS RESTARTS AGE LABELS
kubia-4gj44 1/1 Running 0 104m app=kubia
把pod部署到指定的节点服务器
我们不能直接指定服务器的地址来约束pod部署的节点
通过为 节点 设置标签,在部署pod时,使用节点选择器,来选择把pod部署到匹配的节点服务器
下面为名称为192.168.111.193
的节点服务器,添加标签 gpu=true
k label node \192.168.111.193 \gpu=truek get node \-l gpu=true \-L gpu
------------------------------------------------------
NAME STATUS ROLES AGE VERSION GPU
192.168.111.193 Ready node 14d v1.15.2 true
部署文件,其中节点选择器nodeSelector
设置了 通过标签gpu=true 的
节点 来创建容器
cd ~
cat <<EOF > kubia-gpu.yml
apiVersion: v1
kind: Pod
metadata:name: kubia-gpu # pod名
spec:nodeSelector: # 节点选择器,把pod部署到匹配的节点gpu: "true" # 通过标签 gpu=true 来选择匹配的节点containers: # 容器配置- image: luksa/kubia # 镜像name: kubia # 容器名imagePullPolicy: Never
EOF
创建pod kubia-gpu
,并查看pod的部署节点
k create -f kubia-gpu.ymlk get po -o wide
----------------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubia-5rz9h 1/1 Running 0 3m13s 172.20.2.35 192.168.64.192 <none> <none>
kubia-gpu 1/1 Running 0 8m7s 172.20.3.35 192.168.64.193 <none> <none>
kubia-manual 1/1 Running 0 58m 172.20.3.33 192.168.64.193 <none> <none>
kubia-manual-v2 1/1 Running 0 57m 172.20.3.34 192.168.64.193 <none> <none>
查看pod kubia-gpu
的描述
k describe po kubia-gpu
------------------------------------------------
Name: kubia-gpu
Namespace: default
Priority: 0
Node: 192.168.111.193/192.168.111.193
......
namespace
可以使用命名空间对资源进行组织管理
不同命名空间的资源并不完全隔离,它们之间可以通过网络互相访问
查看命名空间
# namespace
k get ns#查看指定名称空间下的容器
k get po --namespace kube-system
k get po -n kube-system
创建命名空间
新建部署文件custom-namespace.yml
,创建命名空间,命名为custom-namespace
cat <<EOF > custom-namespace.yml
apiVersion: v1
kind: Namespace
metadata:name: custom-namespace
EOF
# 创建命名空间
k create -f custom-namespace.yml k get ns
--------------------------------
NAME STATUS AGE
custom-namespace Active 2s
default Active 6d
kube-node-lease Active 6d
kube-public Active 6d
kube-system Active 6d
将pod部署到指定的命名空间中
创建pod,并将其部署到命名空间custom-namespace
# 创建 Pod 时指定命名空间
k create \-f kubia-manual.yml \-n custom-namespace# 默认访问default命名空间,默认命名空间中不存在pod kubia-manual
k get po kubia-manual# 访问custom-namespace命名空间中的pod
k get po kubia-manual -n custom-namespace
----------------------------------------------------------
NAME READY STATUS RESTARTS AGE
kubia-manual 0/1 ContainerCreating 0 59s
删除资源
# 按名称删除, 可以指定多个名称
# 例如: k delete po po1 po2 po3
k delete po kubia-gpu# 按标签删除
k delete po -l creation_method=manual# 删除命名空间和其中所有的pod
k delete ns custom-namespace# 删除当前命名空间中所有pod
k delete po --all# 由于有ReplicationController,所以会自动创建新的pod
[root@master1 ~]# k get po
NAME READY STATUS RESTARTS AGE
kubia-m6k4d 1/1 Running 0 2m20s
kubia-rkm58 1/1 Running 0 2m15s
kubia-v4cmh 1/1 Running 0 2m15s# 删除工作空间中所有类型中的所有资源
# 这个操作会删除一个系统Service kubernetes,它被删除后会立即被自动重建
k delete all --all
存活探针
有三种存活探针:
-
HTTP GET
返回 2xx 或 3xx 响应码则认为探测成功
-
TCP
与指定端口建立 TCP 连接,连接成功则为成功
-
Exec
在容器内执行任意的指定命令,并检查命令的退出码,退出码为0则为探测成功
HTTP GET 存活探针
luksa/kubia-unhealthy 镜像
在kubia-unhealthy镜像中,应用程序作了这样的设定: 从第6次请求开始会返回500错
在部署文件中,我们添加探针,来探测容器的健康状态.
探针默认每10秒探测一次,连续三次探测失败后重启容器
cat <<EOF > kubia-liveness-probe.yml
apiVersion: v1
kind: Pod
metadata:name: kubia-liveness # pod名称
spec:containers:- image: luksa/kubia-unhealthy # 镜像name: kubia # 容器名imagePullPolicy: NeverlivenessProbe: # 存活探针配置httpGet: # HTTP GET 类型的存活探针path: / # 探测路径port: 8080 # 探测端口
EOF
创建 pod
k create -f kubia-liveness-probe.yml# pod的RESTARTS属性,每过1分半种就会加1
k get po kubia-liveness
--------------------------------------------------
NAME READY STATUS RESTARTS AGE
kubia-liveness 1/1 Running 0 5m25s
查看上一个pod的日志,前5次探测是正确状态,后面3次探测是失败的,则该pod会被删除
k logs kubia-liveness
-----------------------------------------
Kubia server starting...
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
查看pod描述
k describe po kubia-liveness
---------------------------------
......Restart Count: 6Liveness: http-get http://:8080/ delay=0s timeout=1s period=10s #success=1 #failure=3
......
delay
0表示容器启动后立即开始探测timeout
1表示必须在1秒内响应,否则视为探测失败period
10s表示每10秒探测一次failure
3表示连续3次失败后重启容器
通过设置 delay 延迟时间,可以避免在容器内应用没有完全启动的情况下就开始探测
cat <<EOF > kubia-liveness-probe-initial-delay.yml
apiVersion: v1
kind: Pod
metadata:name: kubia-liveness
spec:containers:- image: luksa/kubia-unhealthyname: kubiaimagePullPolicy: NeverlivenessProbe:httpGet:path: /port: 8080initialDelaySeconds: 15 # 第一次探测的延迟时间
EOF
删除刚刚启动的容器,重新部署
kubectl delete po kubia-liveness
k create -f kubia-liveness-probe.ymlk get po kubia-livenessk logs kubia-liveness
控制器
ReplicationController
RC可以自动化维护多个pod,只需指定pod副本的数量,就可以轻松实现自动扩容缩容
当一个pod宕机,RC可以自动关闭pod,并启动一个新的pod替代它
下面是一个RC的部署文件,设置启动三个kubia容器:
cat <<EOF > kubia-rc.yml
apiVersion: v1
kind: ReplicationController # 资源类型
metadata: name: kubia # 为RC命名
spec:replicas: 3 # pod副本的数量selector: # 选择器,用来选择RC管理的podapp: kubia # 选择标签'app=kubia'的pod,由当前RC进行管理template: # pod模板,用来创建新的podmetadata:labels:app: kubia # 指定pod的标签spec:containers: # 容器配置- name: kubia # 容器名image: luksa/kubia # 镜像imagePullPolicy: Neverports:- containerPort: 8080 # 容器暴露的端口
EOF
创建RC
RC创建后,会根据指定的pod数量3,自动创建3个pod
k create -f kubia-rc.ymlk get rc
----------------------------------------
NAME DESIRED CURRENT READY AGE
kubia 3 3 2 2m11sk get po -o wide
------------------------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubia-fmtkw 1/1 Running 0 9m2s 172.20.1.7 192.168.64.192 <none> <none>
kubia-lc5qv 1/1 Running 0 9m3s 172.20.1.8 192.168.64.192 <none> <none>
kubia-pjs9n 1/1 Running 0 9m2s 172.20.2.11 192.168.64.193 <none> <none>
RC是通过指定的标签app=kubia
对匹配的pod进行管理的
允许在pod上添加任何其他标签,而不会影响pod与RC的关联关系
k label pod kubia-fmtkw type=specialk get po --show-labels
----------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE LABELS
kubia-fmtkw 1/1 Running 0 6h31m app=kubia,type=special
kubia-lc5qv 1/1 Running 0 6h31m app=kubia
kubia-pjs9n 1/1 Running 0 6h31m app=kubia
但是,如果改变pod的app标签的值,就会使这个pod脱离RC的管理,这样RC会认为这里少了一个pod,那么它会立即创建一个新的pod,来满足我们设置的3个pod的要求
k label pod kubia-fmtkw app=foo --overwritek get pods -L app
-------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE APP
kubia-fmtkw 1/1 Running 0 6h36m foo
kubia-lc5qv 1/1 Running 0 6h36m kubia
kubia-lhj4q 0/1 Pending 0 6s kubia
kubia-pjs9n 1/1 Running 0 6h36m kubia
修改 pod 模板
pod模板修改后,只影响后续新建的pod,已创建的pod不会被修改
可以删除旧的pod,用新的pod来替代
# 编辑 ReplicationController,添加一个新的标签: foo=bar
k edit rc kubia
------------------------------------------------
......
spec:replicas: 3selector:app: kubiatemplate:metadata:creationTimestamp: nulllabels:app: kubiafoo: bar # 任意添加一标签spec:
......# 之前pod的标签没有改变
k get pods --show-labels
----------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE LABELS
kubia-lc5qv 1/1 Running 0 3d5h app=kubia
kubia-lhj4q 1/1 Running 0 2d22h app=kubia
kubia-pjs9n 1/1 Running 0 3d5h app=kubia# 通过RC,把pod扩容到6个
# 可以使用前面用过的scale命令来扩容
# k scale rc kubia --replicas=6# 或者,可以编辑修改RC的replicas属性,修改成6
k edit rc kubia
---------------------
spec:replicas: 6 # 从3修改成6,扩容到6个podselector:app: kubia# 新增加的pod有新的标签,而旧的pod没有新标签
k get pods --show-labels
----------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE LABELS
kubia-8d9jj 0/1 Pending 0 2m23s app=kubia,foo=bar
kubia-lc5qv 1/1 Running 0 3d5h app=kubia
kubia-lhj4q 1/1 Running 0 2d22h app=kubia
kubia-pjs9n 1/1 Running 0 3d5h app=kubia
kubia-wb8sv 0/1 Pending 0 2m17s app=kubia,foo=bar
kubia-xp4jv 0/1 Pending 0 2m17s app=kubia,foo=bar# 删除 rc, 但不级联删除 pod, 使 pod 处于脱管状态
k delete rc kubia --cascade=false
ReplicaSet
ReplicaSet 被设计用来替代 ReplicationController,它提供了更丰富的pod选择功能
以后我们总应该使用 RS, 而不适用 RC, 但在旧系统中仍会使用 RC
cat <<EOF > kubia-replicaset.yml
apiVersion: apps/v1 # RS 是 apps/v1中提供的资源类型
kind: ReplicaSet # 资源类型
metadata:name: kubia # RS 命名为 kubia
spec:replicas: 3 # pod 副本数量selector:matchLabels: # 使用 label 选择器app: kubia # 选取标签是 "app=kubia" 的podtemplate:metadata:labels:app: kubia # 为创建的pod添加标签 "app=kubia"spec:containers:- name: kubia # 容器名image: luksa/kubia # 镜像imagePullPolicy: Never
EOF
k get po --show-labels
创建 ReplicaSet
k create -f kubia-replicaset.yml# 之前脱离管理的pod被RS管理
# 设置的pod数量是3,多出的pod会被关闭
k get rs
----------------------------------------
NAME DESIRED CURRENT READY AGE
kubia 3 3 3 4s# 多出的3个pod会被关闭
k get pods --show-labels
----------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE LABELS
kubia-8d9jj 1/1 Pending 0 2m23s app=kubia,foo=bar
kubia-lc5qv 1/1 Terminating 0 3d5h app=kubia
kubia-lhj4q 1/1 Terminating 0 2d22h app=kubia
kubia-pjs9n 1/1 Running 0 3d5h app=kubia
kubia-wb8sv 1/1 Pending 0 2m17s app=kubia,foo=bar
kubia-xp4jv 1/1 Terminating 0 2m17s app=kubia,foo=bar# 查看RS描述, 与RC几乎相同
k describe rs kubia
使用更强大的标签选择器
cat <<EOF > kubia-replicaset.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:name: kubia
spec:replicas: 4selector:matchExpressions: # 表达式匹配选择器- key: app # label 名是 appoperator: In # in 运算符values: # label 值列表- kubia- footemplate:metadata:labels:app: kubiaspec:containers:- name: kubiaimage: luksa/kubiaimagePullPolicy: Never
EOF
# 先删除现有 RS, 删除控制器kubia,保留rc控制的容器
k delete rs kubia --cascade=orphan# 再创建 RS
k create -f kubia-replicaset.yml# 查看rs
k get rs
# 查看pod
k get po --show-labels
可使用的运算符:
In
: label与其中一个值匹配NotIn
: label与任何一个值都不匹配Exists
: 包含指定label名称值任意)DoesNotExists
: 不包含指定的label
清理
k delete rs kubiak get rs
k get po
DaemonSet
在每个节点上运行一个 pod,例如资源监控,比如监控每台节点的硬盘使用情况,kube-proxy等
DaemonSet不指定pod数量,它会在每个节点上部署一个pod
cat <<EOF > ssd-monitor-daemonset.yml
apiVersion: apps/v1
kind: DaemonSet # 资源类型
metadata:name: ssd-monitor # DS资源命名
spec:selector:matchLabels: # 标签匹配器app: ssd-monitor # 匹配的标签template:metadata:labels:app: ssd-monitor # 创建pod时,添加标签spec:containers: # 容器配置- name: main # 容器命名image: luksa/ssd-monitor # 镜像imagePullPolicy: Never
EOF
创建 DS
DS 创建后,会在所有节点上创建pod,包括master
k create -f ssd-monitor-daemonset.ymlk get po -o wide
-------------------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ssd-monitor-g7fjb 1/1 Running 0 57m 172.20.1.12 192.168.64.192 <none> <none>
ssd-monitor-qk6t5 1/1 Running 0 57m 172.20.2.14 192.168.64.193 <none> <none>
ssd-monitor-xxbq8 1/1 Running 0 57m 172.20.0.2 192.168.64.191 <none> <none>
可以在所有选定的节点上部署pod
通过节点的label来选择节点
cat <<EOF > ssd-monitor-daemonset.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:name: ssd-monitor
spec:selector:matchLabels: app: ssd-monitor template:metadata:labels:app: ssd-monitor spec:nodeSelector: # 节点选择器disk: ssd # 选择的节点上具有标签: 'disk=ssd'containers: - name: main image: luksa/ssd-monitor imagePullPolicy: Never
EOF
# 先清理
k delete ds ssd-monitor# 再重新创建
k create -f ssd-monitor-daemonset.yml
查看 DS 和 pod, 看到并没有创建pod,这是因为不存在具有disk=ssd
标签的节点
k get dsk get po
为节点’192.168.111.192’设置标签 disk=ssd
这样 DS 会在该节点上立即创建 pod
k label node 192.168.111.192 disk=ssdk get ds
---------------------------------------------------------------------------------------
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
ssd-monitor 1 1 0 1 0 disk=ssd 37mk get po -o wide
----------------------------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ssd-monitor-n6d45 1/1 Running 0 16s 172.20.1.13 192.168.64.192 <none> <none>
同样,进一步测试,为节点’192.168.111.193’设置标签 disk=ssd
k label node 192.168.111.193 disk=ssd
k get ds
k get po -o wide
删除’192.168.111.193’节点上的disk
标签,那么该节点中部署的pod会被立即销毁
# 注意删除格式: disk-
k label node 192.168.111.193 disk-
k get ds
k get po -o wide
清理
k delete ds ssd-monitor
Job
Job 用来运行单个任务,任务结束后pod不再重启
cat <<EOF > exporter.yml
apiVersion: batch/v1 # Job资源在batch/v1版本中提供
kind: Job # 资源类型
metadata: name: batch-job # 资源命名
spec:template: metadata:labels:app: batch-job # pod容器标签spec:restartPolicy: OnFailure # 任务失败时重启containers:- name: main # 容器名image: luksa/batch-job # 镜像imagePullPolicy: Never
EOF
创建 job
镜像 batch-job 中的进程,运行120秒后会自动退出
k create -f exporter.ymlk get job
-----------------------------------------
NAME COMPLETIONS DURATION AGE
batch-job 0/1 7sk get po
-------------------------------------------------------------
NAME READY STATUS RESTARTS AGE
batch-job-q97zf 0/1 ContainerCreating 0 7s
等待两分钟后,pod中执行的任务退出,再查看job和pod
k get job
-----------------------------------------
NAME COMPLETIONS DURATION AGE
batch-job 1/1 2m5s 2m16sk get po
-----------------------------------------------------
NAME READY STATUS RESTARTS AGE
batch-job-q97zf 0/1 Completed 0 2m20s
使用Job让pod连续运行5次
先创建第一个pod,等第一个完成后后,再创建第二个pod,以此类推,共顺序完成5个pod
cat <<EOF > multi-completion-batch-job.yml
apiVersion: batch/v1
kind: Job
metadata: name: multi-completion-batch-job
spec:completions: 5 # 指定完整的数量template: metadata:labels:app: batch-jobspec:restartPolicy: OnFailurecontainers:- name: mainimage: luksa/batch-jobimagePullPolicy: Never
EOF
k create -f multi-completion-batch-job.yml
共完成5个pod,并每次可以同时启动两个pod
cat <<EOF > multi-completion-parallel-batch-job.yml
apiVersion: batch/v1
kind: Job
metadata: name: multi-completion-parallel-batch-job
spec:completions: 5 # 共完成5个parallelism: 2 # 可以有两个pod同时执行template: metadata:labels:app: batch-jobspec:restartPolicy: OnFailurecontainers:- name: mainimage: luksa/batch-jobimagePullPolicy: Never
EOF
k create -f multi-completion-parallel-batch-job.yml
Cronjob
定时和重复执行的任务
cron时间表格式:"分钟 小时 每月的第几天 月 星期几"
cat <<EOF > cronjob.yml
apiVersion: batch/v1beta1 # api版本
kind: CronJob # 资源类型
metadata:name: batch-job-every-fifteen-minutes
spec:# 0,15,30,45 - 分钟# 第一个* - 每个小时# 第二个* - 每月的每一天# 第三个* - 每月# 第四个* - 每一周中的每一天schedule: "0,15,30,45 * * * *"jobTemplate:spec:template:metadata:labels:app: periodic-batch-jobspec:restartPolicy: OnFailurecontainers: - name: mainimage: luksa/batch-jobimagePullPolicy: Never
EOF
创建cronjob
k create -f cronjob.yml# 立即查看 cronjob,此时还没有创建pod
k get cj
----------------------------------------------------------------------------------------------
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
batch-job-every-fifteen-minutes 0,15,30,45 * * * * False 1 27s 2m17s# 到0,15,30,45分钟时,会创建一个pod
k get po
--------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE
batch-job-every-fifteen-minutes-1567649700-vlmdw 1/1 Running 0 36s
控制面板-管理界面
查询系统空间下的一个dashboard控制页面对外暴露的端口随机)32550
k get svc -n kube-system
---------------------------------------------------------------
kubernetes-dashboard NodePort 10.68.205.116 <none> 443:32550/TCP 8h
浏览器访问:https://192.168.111.191:32550
# 获取 Bearer Token,复制输出中 ‘token:’ 开头那一行
k -n kube-system describe secret $kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')
输入获取到的token,点击登录。
在管理界面 ,执行创建命令,类似 k create -f 文件.yml
apiVersion: apps/v1 # RS 是 apps/v1中提供的资源类型
kind: ReplicaSet # 资源类型
metadata:name: kubia # RS 命名为 kubia
spec:replicas: 3 # pod 副本数量selector:matchLabels: # 使用 label 选择器app: kubia # 选取标签是 "app=kubia" 的podtemplate:metadata:labels:app: kubia # 为创建的pod添加标签 "app=kubia"spec:containers:- name: kubia # 容器名image: luksa/kubia # 镜像imagePullPolicy: Never
Service
主要3个参数:
1、自己的端口
2、调用目标容器的端口
3、容器选择器
通过Service资源,为多个pod提供一个单一不变的接入地址
cat <<EOF > kubia-svc.yml
apiVersion: v1
kind: Service # 资源类型
metadata:name: kubia # 资源命名
spec:ports:- port: 80 # Service向外暴露的端口targetPort: 8080 # 容器的端口selector:app: kubia # 通过标签,选择名为kubia的所有pod
EOF
k create -f kubia-svc.ymlk get svc
--------------------------------------------------------------------
NAME TYPE CLUSTER-IP EXTERNAL-IP PORTS) AGE
kubernetes ClusterIP 10.68.0.1 <none> 443/TCP 2d11h
kubia ClusterIP 10.68.163.98 <none> 80/TCP 5s
如果没有pod具有app:kubia标签,可以创建前面的ReplicaSet资源,并让RS自动创建pod,全文搜索下这篇博客就可以找到kubia-replicaset.yml文件
k create -f kubia-replicaset.yml
从内部网络访问Service
执行curl http://10.68.163.98
来访问Service
执行多次会看到,Service会在多个pod中轮训发送请求
curl http://10.68.163.98# [root@localhost ~]# curl http://10.68.163.98
# You've hit kubia-xdj86
# [root@localhost ~]# curl http://10.68.163.98
# You've hit kubia-xmtq2
# [root@localhost ~]# curl http://10.68.163.98
# You've hit kubia-5zm2q
# [root@localhost ~]# curl http://10.68.163.98
# You've hit kubia-xdj86
# [root@localhost ~]# curl http://10.68.163.98
# You've hit kubia-xmtq2
会话亲和性
来自同一个客户端的请求,总是发给同一个pod
cat <<EOF > kubia-svc-clientip.yml
apiVersion: v1
kind: Service
metadata:name: kubia-clientip
spec:sessionAffinity: ClientIP # 会话亲和性使用ClientIPports:- port: 80targetPort: 8080selector:app: kubia
EOF
k create -f kubia-svc-clientip.ymlk get svc
------------------------------------------------------------------------
NAME TYPE CLUSTER-IP EXTERNAL-IP PORTS) AGE
kubernetes ClusterIP 10.68.0.1 <none> 443/TCP 2d12h
kubia ClusterIP 10.68.163.98 <none> 80/TCP 38m
kubia-clientip ClusterIP 10.68.72.120 <none> 80/TCP 2m15s# 进入kubia-5zm2q容器,向Service发送请求
# 执行多次会看到,每次请求的都是同一个pod
curl http://10.68.72.120
endpoint,端点/地址列表
一般用来调用外部系统,地址列表就是外部系统的地址。
endpoint是在Service和pod之间的一种资源
一个endpoint资源,包含一组pod的地址列表
创建一个service
不含pod选择器的服务,不会创建 endpoint
cat <<EOF > external-service.yml
apiVersion: v1
kind: Service
metadata:name: external-service # Service命名
spec:ports:- port: 80
EOF
# 创建没有选择器的 Service,不会创建Endpoint
k create -f external-service.yml# 查看Service
k get svc# 通过内部网络ip访问Service,没有Endpoint地址列表,会拒绝连接
curl http://10.68.191.212
创建endpoint关联到Service,它的名字必须与Service同名
cat <<EOF > external-service-endpoints.yml
apiVersion: v1
kind: Endpoints # 资源类型
metadata:name: external-service # 名称要与Service名相匹配
subsets:
- addresses: # 包含的地址列表- ip: 120.52.99.224 # 中国联通的ip地址- ip: 117.136.190.162 # 中国移动的ip地址ports:- port: 80 # 目标服务的的端口
EOF
# 创建Endpoint
k create -f external-service-endpoints.ymlk get ep
[root@centos00 ~]# k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORTS) AGE
external-service ClusterIP 10.68.76.158 <none> 80/TCP 18s
# 访问 external-service
# 多次访问,会在endpoints地址列表中轮训请求
curl http://10.68.76.158
k get po# 随便进入一个pod容器
k exec -it kubia-k66lz bash# 访问 external-service
# 多次访问,会在endpoints地址列表中轮训请求
curl http://external-service
通过完全限定域名
访问外部服务
cat <<EOF > external-service-externalname.yml
apiVersion: v1
kind: Service
metadata:name: external-service-externalname
spec:type: ExternalNameexternalName: www.chinaunicom.com.cn # 域名ports:- port: 80
EOF
创建服务
k create -f external-service-externalname.yml# 进入一个容器
k exec -it kubia-k66lz bash# 访问 external-service-externalname
curl http://external-service-externalname
服务暴露给客户端
前面创建的Service只能在集群内部网络中访问,那么怎么让客户端来访问Service呢?
三种方式
- NodePort
- 每个节点都开放一个端口
- LoadBalance
- NodePort的一种扩展,负载均衡器需要云基础设施来提供
- Ingress
NodePort
3个端口,自己的端口,访问的容器的端口,外部访问的端口
在每个节点包括master),都开放一个相同的端口,可以通过任意节点的端口来访问Service
cat <<EOF > kubia-svc-nodeport.yml
apiVersion: v1
kind: Service
metadata:name: kubia-nodeport
spec:type: NodePort # 在每个节点上开放访问端口ports:- port: 80 # 集群内部访问该服务的端口targetPort: 8080 # 容器的端口nodePort: 30123 # 外部访问端口selector:app: kubia
EOF
创建并查看 Service
k create -f kubia-svc-nodeport.ymlk get svc kubia-nodeport
-----------------------------------------------------------------------------
NAME TYPE CLUSTER-IP EXTERNAL-IP PORTS) AGE
kubia-nodeport NodePort 10.68.140.119 <none> 80:30123/TCP 14m
可以通过任意节点的30123
端口来访问 Service
浏览器访问:
- http://192.168.111.191:30123
- http://192.168.111.192:30123
- http://192.168.111.193:30123
磁盘挂载到容器
卷
卷的类型:
- emptyDir: 简单的空目录,临时的在pod中的多个容器之间数据共享
- hostPath: 工作节点中的磁盘路径
- gitRepo: 从git克隆的本地仓库
- nfs: nfs共享文件系统
创建包含两个容器的pod, 它们共享同一个卷
cat <<EOF > fortune-pod.yml
apiVersion: v1
kind: Pod
metadata:name: fortunelabels:app: fortune
spec:containers:- image: luksa/fortune # 镜像名name: html-genrator # 容器名imagePullPolicy: NevervolumeMounts:- name: html # 卷名为 htmlmountPath: /var/htdocs # 容器中的挂载路径- image: nginx:alpine # 第二个镜像名name: web-server # 第二个容器名imagePullPolicy: NevervolumeMounts:- name: html # 相同的卷 htmlmountPath: /usr/share/nginx/html # 在第二个容器中的挂载路径readOnly: true # 设置为只读ports:- containerPort: 80protocol: TCPvolumes: # 卷- name: html # 为卷命名emptyDir: {} # emptyDir类型的卷
EOF
k create -f fortune-pod.ymlk get po
创建Service, 通过这个Service访问pod的80端口
cat <<EOF > fortune-svc.yml
apiVersion: v1
kind: Service
metadata:name: fortune
spec:type: NodePortports:- port: 8088targetPort: 80nodePort: 31088selector:app: fortune
EOF
k create -f fortune-svc.ymlk get svc# 用浏览器访问 http://192.168.111.191:31088/
NFS 文件系统
NFS共享目录
在三台服务器上安装 nfs:
yum install -y dnf
dnf install nfs-utils
在 master 节点 192.168.111.191 上创建 nfs 目录 /etc/nfs_data
,
并允许 1921.68.111 网段的主机共享访问这个目录
# 创建文件夹
mkdir /etc/nfs_data# 在exports文件夹中写入配置
# no_root_squash: 服务器端使用root权限
cat <<EOF > /etc/exports
/etc/nfs_data 192.168.111.0/24rw,async,no_root_squash)
EOF
systemctl enable nfs-server
systemctl enable rpcbind
systemctl start nfs-server
systemctl start rpcbind
尝试在192.168.111.192,挂载远程的nfs目录
# 新建挂载目录
mkdir /etc/web_dir/# 在客户端, 挂载服务器的 nfs 目录
mount -t nfs 192.168.111.191:/etc/nfs_data /etc/web_dir/
测试
在192.168.111.192执行
echo 11111 > /etc/web_dir/test.txt
在192.168.111.191 查看
[root@centos00 nfs_data]# cat /etc/nfs_data/test.txt
-----------------------------------------------------
11111
持久化存储
创建 PersistentVolume – 持久卷
cat <<EOF > mongodb-pv.yml
apiVersion: v1
kind: PersistentVolume
metadata: name: mongodb-pv
spec:capacity:storage: 1Gi # 定义持久卷大小accessModes:- ReadWriteOnce # 只允许被一个客户端挂载为读写模式- ReadOnlyMany # 可以被多个客户端挂载为只读模式persistentVolumeReclaimPolicy: Retain # 当声明被释放,持久卷将被保留nfs: # nfs远程目录定义path: /etc/nfs_dataserver: 192.168.111.191
EOF
# 创建持久卷
k create -f mongodb-pv.yml# 查看持久卷
k get pv
----------------------------------------------------------------------------------------------------------
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
mongodb-pv 1Gi RWO,ROX Retain Available 4s
创建持久卷声明
使用持久卷声明,使应用与底层存储技术解耦
cat <<EOF > mongodb-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata: name: mongodb-pvc
spec:resources:requests:storage: 1Gi # 申请1GiB存储空间accessModes:- ReadWriteOnce # 允许单个客户端读写storageClassName: "" # 参考动态配置章节
EOF
k create -f mongodb-pvc.ymlk get pvc
-----------------------------------------------------------------------------------
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mongodb-pvc Bound mongodb-pv 1Gi RWO,ROX 3s
创建mongodb容器
cat <<EOF > mongodb-pod-pvc.yml
apiVersion: v1
kind: Pod
metadata:name: mongodb
spec:containers:- image: mongoname: mongodbimagePullPolicy: NeversecurityContext:runAsUser: 0volumeMounts:- name: mongodb-datamountPath: /data/dbports:- containerPort: 27017protocol: TCPvolumes:- name: mongodb-datapersistentVolumeClaim:claimName: mongodb-pvc # 引用之前创建的"持久卷声明"
EOF
验证 pod 中加挂载了 nfs 远程目录作为持久卷
k create -f mongodb-pod-pvc.ymlk exec -it mongodb mongouse mystore
db.foo.insert{name:'foo'})
db.foo.find)exit
查看在 nfs 远程目录中的文件
cd /etc/nfs_data
ls
配置启动参数
启动jar包,可以使用启动参数,可以覆盖jar包中自带的端口号
java -jar app.jar –server.port=8081
docker可以再次修改默认的启动参数
CMD ["–server.port=8082"]
k8s还可以再次覆盖docker的启动参数args
可以覆盖CMD
args: ["
–server.port=8082"]
k8s还可以使用环境变量env
docker 的命令行参数
Dockerfile中定义命令和参数的指令
ENTRYPOINT
启动容器时,在容器内执行的命令CMD
对启动命令传递的参数
CMD
可以在docker run
命令中进行覆盖
例如:
......
ENTRYPOINT ["java", "-jar", "/opt/sp05-eureka-0.0.1-SNAPSHOT.jar"]
CMD ["--spring.profiles.active=eureka1"]
启动容器时,可以执行:
docker run <image>
或者启动容器时覆盖CMD
docker run <image> --spring.profiles.active=eureka2
k8s中覆盖docker的ENTRYPOINT
和CMD
command
可以覆盖ENTRYPOINT
args
可以覆盖CMD
在镜像luksa/fortune:args
中,设置了自动生成内容的间隔时间参数为10秒
......
CMD ["10"]
可以通过k8s的args
来覆盖docker的CMD
cat <<EOF > fortune-pod-args.yml
apiVersion: v1
kind: Pod
metadata:name: fortunelabels:app: fortune
spec:containers:- image: luksa/fortune:argsargs: ["2"] # docker镜像中配置的CMD是10,这里用args把这个值覆盖成2name: html-genratorimagePullPolicy: NevervolumeMounts:- name: htmlmountPath: /var/htdocs- image: nginx:alpinename: web-serverimagePullPolicy: NevervolumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlreadOnly: trueports:- containerPort: 80protocol: TCPvolumes:- name: htmlemptyDir: {}
EOF
k create -f fortune-pod-args.yml# 查看pod
k get po -o wide
--------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
fortune 2/2 Running 0 34s 172.20.2.55 192.168.111.192 <none> <none>
重复地执行curl命令,访问该pod,会看到数据每2秒刷新一次
注意要修改成你的pod的ip
curl http://172.20.2.55
环境变量
在镜像luksa/fortune:env
中通过环境变量INTERVAL
来指定内容生成的间隔时间
下面配置中,通过env
配置,在容器中设置了环境变量INTERVAL
的值
cat <<EOF > fortune-pod-env.yml
apiVersion: v1
kind: Pod
metadata:name: fortunelabels:app: fortune
spec:containers:- image: luksa/fortune:envenv: # 设置环境变量 INTERVAL=5- name: INTERVALvalue: "5"name: html-genratorimagePullPolicy: NevervolumeMounts:- name: htmlmountPath: /var/htdocs- image: nginx:alpinename: web-serverimagePullPolicy: NevervolumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlreadOnly: trueports:- containerPort: 80protocol: TCPvolumes:- name: htmlemptyDir: {}
EOF
k delete po fortune
k create -f fortune-pod-env.yml # 查看pod
k get po -o wide
--------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
fortune 2/2 Running 0 8s 172.20.2.56 192.168.64.192 <none> <none># 进入pod
k exec -it fortune bash
# 查看pod的环境变量
env
------------
INTERVAL=5
......# 从pod推出,回到宿主机
exit
重复地执行curl命令,访问该pod,会看到数据每5秒刷新一次
注意要修改成你的pod的ip
curl http://172.20.2.56
ConfigMap
通过ConfigMap资源,集中存储环境变量,可以从pod中把环境变量配置分离出来,是环境变量配置与pod解耦
可以从命令行创建ConfigMap资源:
# 直接命令行创建
k create configmap fortune-config --from-literal=sleep-interval=20
或者从部署文件创建ConfigMap:
# 或从文件创建
cat <<EOF > fortune-config.yml
apiVersion: v1
kind: ConfigMap
metadata:name: fortune-config
data:sleep-interval: "10"
EOF
# 创建ConfigMap
k create -f fortune-config.yml# 查看ConfigMap的配置
k get cm fortune-config -o yaml
从ConfigMap获取配置数据,设置为pod的环境变量
cat <<EOF > fortune-pod-env-configmap.yml
apiVersion: v1
kind: Pod
metadata:name: fortunelabels:app: fortune
spec:containers:- image: luksa/fortune:envimagePullPolicy: Neverenv:- name: INTERVAL # 环境变量名valueFrom:configMapKeyRef: # 环境变量的值从ConfigMap获取name: fortune-config # 使用的ConfigMap名称key: sleep-interval # 用指定的键从ConfigMap取数据name: html-genratorvolumeMounts:- name: htmlmountPath: /var/htdocs- image: nginx:alpineimagePullPolicy: Nevername: web-servervolumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlreadOnly: trueports:- containerPort: 80protocol: TCPvolumes:- name: htmlemptyDir: {}
EOF
k create -f fortune-pod-env-configmap.yml
Deployment
Deployment 是一种更高级的资源,用于部署或升级应用.
创建Deployment时,ReplicaSet资源会随之创建,实际Pod是由ReplicaSet创建和管理,而不是由Deployment直接管理
Deployment可以在应用滚动升级过程中, 引入另一个RepliaSet, 并协调两个ReplicaSet.
cat <<EOF > kubia-deployment-v1.yml
apiVersion: apps/v1
kind: Deployment
metadata:name: kubia
spec:replicas: 3selector: matchLabels:app: kubiatemplate:metadata:name: kubialabels:app: kubiaspec:containers:- image: luksa/kubia:v1imagePullPolicy: Nevername: nodejs
EOF
k create -f kubia-deployment-v1.yml --recordk get deploy
-----------------------------------------------
NAME READY UP-TO-DATE AVAILABLE AGE
kubia 3/3 3 3 2m35sk get rs
----------------------------------------------------
NAME DESIRED CURRENT READY AGE
kubia-66b4657d7b 3 3 3 3m4sk get po
------------------------------------------------------------
NAME READY STATUS RESTARTS AGE
kubia-66b4657d7b-f9bn7 1/1 Running 0 3m12s
kubia-66b4657d7b-kzqwt 1/1 Running 0 3m12s
kubia-66b4657d7b-zm4xd 1/1 Running 0 3m12sk rollout status deploy kubia
------------------------------------------
deployment "kubia" successfully rolled out
rs 和 pod 名称中的数字,是 pod 模板的哈希值
创建一个service来访问测试
cat <<EOF > kubia-svc-nodeport.yml
apiVersion: v1
kind: Service
metadata:name: kubia-nodeport
spec:type: NodePort # 在每个节点上开放访问端口ports:- port: 80 # 集群内部访问该服务的端口targetPort: 8080 # 容器的端口nodePort: 30123 # 外部访问端口selector:app: kubia
EOF
k create -f kubia-svc-nodeport.ymlk get svc kubia-nodeport
-----------------------------------------------------------------------------
NAME TYPE CLUSTER-IP EXTERNAL-IP PORTS) AGE
kubia-nodeport NodePort 10.68.140.119 <none> 80:30123/TCP 14m
可以通过任意节点的30123
端口来访问 Service
- http://192.168.111.191:30123
- http://192.168.111.192:30123
- http://192.168.111.193:30123
升级 Deployment
只需要在 pod 模板中修改镜像的 Tag, Deployment 就可以自动完成升级过程
Deployment的升级策略
- 滚动升级 Rolling Update – 渐进的删除旧的pod, 同时创建新的pod, 这是默认的升级策略
- 重建 Recreate – 一次删除所有旧的pod, 再重新创建新的pod
minReadySeconds
设置为10秒, 减慢滚动升级速度, 便于我们观察升级的过程.
k patch deploy kubia -p '{"spec": {"minReadySeconds": 10}}'
触发滚动升级
修改 Deployment 中 pod 模板使用的镜像就可以触发滚动升级
为了便于观察, 在另一个终端中执行循环, 通过 service 来访问pod
while true; do curl http://192.168.111.191:30123; sleep 0.5s; done
修改镜像版本
k set image deploy kubia nodejs=luksa/kubia:v2
通过不同的命令来了解升级的过程和原理
k rollout status deploy kubia
k get rs
k get po --show-labels
k describe rs kubia-66b4657d7b
回滚 Deployment
luksa/kubia:v3 镜像中的应用模拟一个 bug, 从第5次请求开始, 会出现 500 错误
k set image deploy kubia nodejs=luksa/kubia:v3
手动回滚到上一个版本
k rollout undo deploy kubia
控制滚动升级速率
滚动升级时
- 先创建新版本pod
- 再销毁旧版本pod
可以通过参数来控制, 每次新建的pod数量和销毁的pod数量:
maxSurge
– 默认25%
允许超出的 pod 数量.
如果期望pod数量是4, 滚动升级期间, 最多只允许实际有5个 pod.maxUnavailable
– 默认 25%
允许有多少 pod 处于不可用状态.必须保证可用数量最少为maxUnavailable
。
如果期望pod数量是4, 滚动升级期间, 最多只允许 1 个 pod 不可用, 也就是说任何时间都要保持至少有 3 个可用的pod.
查看参数
k get deploy -o yaml
--------------------------------
......strategy:rollingUpdate:maxSurge: 25%maxUnavailable: 25%type: RollingUpdate
......
暂停滚动升级
将 image 升级到 v4 版本触发更新, 并立即暂停更新.
这时会有一个新版本的 pod 启动, 可以暂停更新过程, 让少量用户可以访问到新版本, 并观察其运行是否正常.
根据新版本的运行情况, 可以继续完成更新, 或回滚到旧版本.
k set image deploy kubia nodejs=luksa/kubia:v4# 暂停
k rollout pause deploy kubia# 继续
k rollout resume deploy kubia
自动阻止出错版本升级
minReadySeconds
- 新创建的pod成功运行多久后才,继续升级过程
- 在该时间段内, 如果容器的就绪探针返回失败, 升级过程将被阻止
修改Deployment配置,添加就绪探针
cat <<EOF > kubia-deployment-v3-with-readinesscheck.yml
apiVersion: apps/v1
kind: Deployment
metadata:name: kubia
spec:replicas: 3selector: matchLabels:app: kubiaminReadySeconds: 10strategy:rollingUpdate:maxSurge: 1maxUnavailable: 0type: RollingUpdatetemplate:metadata:name: kubialabels:app: kubiaspec:containers:- image: luksa/kubia:v3name: nodejsimagePullPolicy: NeverreadinessProbe:periodSeconds: 1httpGet:path: /port: 8080
EOF
k apply -f kubia-deployment-v3-with-readinesscheck.yml
就绪探针探测间隔设置成了 1 秒, 第5次请求开始每次请求都返回500错, 容器会处于未就绪状态. minReadySeconds
被设置成了10秒, 只有pod就绪10秒后, 升级过程才会继续.所以这是滚动升级过程会被阻塞, 不会继续进行.
默认升级过程被阻塞10分钟后, 升级过程会被视为失败, Deployment描述中会显示超时ProgressDeadlineExceeded).
k describe deploy kubia
-----------------------------
......
Conditions:Type Status Reason---- ------ ------Available True MinimumReplicasAvailableProgressing False ProgressDeadlineExceeded
......
这是只能通过手动执行 rollout undo 命令进行回滚
k rollout undo deploy kubia
Dashboard 仪表盘
查看 Dashboard 部署信息
# 查看pod
k get pod -n kube-system | grep dashboard
-------------------------------------------------------------------------------
kubernetes-dashboard-5c7687cf8-s2f9z 1/1 Running 0 10d# 查看service
k get svc -n kube-system | grep dashboard
------------------------------------------------------------------------------------------------------
kubernetes-dashboard NodePort 10.68.239.141 <none> 443:20176/TCP 10d# 查看集群信息
k cluster-info | grep dashboard
-------------------------------------------------------------------------------------------------------------------------------------------------------------
kubernetes-dashboard is running at https://192.168.64.191:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy
根据上面信息可以看到 dashboard 的访问地址:
https://192.168.64.191:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy
现在访问 dashboard 由于安全设置的原因无法访问
证书验证访问
使用集群CA 生成客户端证书,该证书拥有所有权限
cd /etc/kubernetes/ssl# 导出证书文件
openssl pkcs12 -export -in admin.pem -inkey admin-key.pem -out kube-admin.p12
下载 /etc/kubernetes/ssl/kube-admin.p12
证书文件, 在浏览器中导入:
访问 dashboard 会提示登录, 这里我们用令牌的方式访问 https://192.168.64.191:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy)
令牌
# 创建Service Account 和 ClusterRoleBinding
k apply -f /etc/ansible/manifests/dashboard/admin-user-sa-rbac.yaml# 获取 Bearer Token,复制输出中 ‘token:’ 开头那一行
k -n kube-system describe secret $kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')
eyJhbGciOiJSUzI1NiIsImtpZCI6InZmYmdUOG4tTTY5VU9PVkh1V1Z4WTlIWjBoeVVXTzVxblBHUHJZbG5ERTgifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLTh3ODVnIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJmNTQ1MGU3Yi04MTBlLTRkMWYtYmJiNC1lYWY4ODBkODFjMDIiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06YWRtaW4tdXNlciJ9.qMJuj4sW7vOTOxtTzgEcJwlIEsPFZ6uBiIs8VbbzrNdJ4YNTKPvrenV5LtVbpnzZlhcNCJGa5CpHr2N4tywWKAtkUp1XZgzWfpQ8ZibGxE_Z6ZYp5LNo8vxl7BVW25nPYiFJMG25lxjTIpIa044AgKh4MTNdzrN4DmcCug0rvq9Bj0kZhwQOXV4jlZm6fZGWZ2RJJEklnI9HKGqf37_F13_xx8KEbgw4wrqb3qh8Vd5DlIo_Lu74YBccQIhxuwTe2QPoNCJS6ztYzNYg5OJr5ocShAwFGtMoPkrahzmiSbBSb9hFVCAgBfqmEE79AMAlTRs3G465Ts8NYcxN3aou2g
查询有哪些控制器
k get rc
k get rs
k get ds
k get job
k get cj
查看有哪些pod容器)
k get po wide –show-labels
k get po -o wide
查询系统空间自带)的容器
k get po -n kube-system
查询系统空间下的一个dashboard控制页面对外暴露的端口随机)
k get svc -n kube-system
删除所有
k delete all –all
给节点贴标签,disk=ssd
k label node 192.168.111.192 disk=ssd
删除节点标签
k label node 192.168.111.193 disk-
-l后面可以跟查询参数
查询虚拟网络,这个虚拟网络可以通过curl访问
k get svc
查询端点,地址列表
k get ep
查看持久卷
k get pv
查询部署或升级
k get deploy
k delete pvc –all
k delete pv –all