关于kubernetes:Kubernetes一安装配置与基本组件原理

4次阅读

共计 37270 个字符,预计需要花费 94 分钟才能阅读完成。

装置 kubernetes 集群

kubernetes 的装置过程极其简单, 对 Linux 运维不相熟的状况下装置 kubernetes 极为艰难, 再加上国内无法访问 google 服务器, 咱们装置 k8s 就更加艰难

kubeasz 我的项目 (https://github.com/easzlab/kubeasz) 极大的简化了 k8s 集群的装置过程, 使咱们能够离线一键装置 k8s 集群

筹备第一台虚拟机

设置虚拟机 cpu

上传离线安装文件

  • ansible 目录上传到 /etc/ 目录下
  • easzup 上传到 /root 目录下

筹备离线装置环境

在 CentOS7 虚拟机中执行上面操作

cd ~/

# 下载 kubeasz 的自动化装置脚本文件: easzup, 如果曾经上传过此文件, 则不用执行这一步
export release=2.2.0
curl -C- -fLO --retry 3 https://github.com/easzlab/kubeasz/releases/download/${release}/easzup

# 对 easzup 文件设置执行权限
chmod +x ./easzup

# 下载离线安装文件, 并装置配置 docker,
# 如果离线文件曾经存在则不会反复下载,
# 离线安装文件寄存门路: /etc/ansible
./easzup -D

# 启动 kubeasz 工具应用的长期容器
./easzup -S

# 进入该容器
docker exec -it kubeasz sh

# 上面命令在容器内执行
# 配置离线装置
cd /etc/ansible
sed -i 's/^INSTALL_SOURCE.*$/INSTALL_SOURCE:"offline"/g' roles/chrony/defaults/main.yml
sed -i 's/^INSTALL_SOURCE.*$/INSTALL_SOURCE:"offline"/g' roles/ex-lb/defaults/main.yml
sed -i 's/^INSTALL_SOURCE.*$/INSTALL_SOURCE:"offline"/g' roles/kube-node/defaults/main.yml
sed -i 's/^INSTALL_SOURCE.*$/INSTALL_SOURCE:"offline"/g' roles/prepare/defaults/main.yml
exit

# 装置 python, 已装置则疏忽这一步
yum install python -y

导入镜像

为了节省时间, 前面课程中应用的 docker 镜像不必再花工夫从网络下载

将课前材料中 images.gz 中的镜像导入 docker

docker load -i images.gz

筹备三台服务器

筹备三台服务器, 一台 master, 两台工作节点, 他们的 ip 地址能够用任意的地址, 最好设置为固定 ip

上面测试中应用的 ip 为:

  • 192.168.64.191
  • 192.168.64.192
  • 192.168.64.193

从第一台虚拟机克隆两台虚拟机

这三台虚拟机, 第一台虚拟机作为 master, 另两台作为工作节点

在 master 上持续配置装置环境

# 装置 pip, 已装置则疏忽这一步
wget -O /etc/yum.repos.d/epel-7.repo https://mirrors.aliyun.com/repo/epel-7.repo
yum install git python-pip -y

# pip 装置 ansible(国内如果装置太慢能够间接用 pip 阿里云减速), 已装置则疏忽这一步
pip install pip --upgrade -i https://mirrors.aliyun.com/pypi/simple/
pip install ansible==2.6.12 netaddr==0.7.19 -i https://mirrors.aliyun.com/pypi/simple/

# 在 ansible 管制端配置免明码登陆其余节点服务器
ssh-keygen -t ed25519 -N '' -f ~/.ssh/id_ed25519

# 公钥复制到所有节点, 包含 master 本人
# 按提醒输出 yes 和 root 管理员的明码
ssh-copy-id 192.168.64.191

ssh-copy-id 192.168.64.192

ssh-copy-id 192.168.64.193

配置集群服务器的 ip

cd /etc/ansible && cp example/hosts.multi-node hosts && vim hosts

如果内存无限, 能够只部署两台服务器进行测试

  • 主服务器既作为管制节点, 又作为工作节点
  • 缩小 etcd 服务数量
# 查看集群主机状态
ansible all -m ping

一键装置 k8s 集群

装置步骤十分多, 工夫较长, 急躁期待装置实现

cd /etc/ansible
ansible-playbook 90.setup.yml

装置胜利后果:

设置 kubectl 命令别名

# 设置 kubectl 命令别名 k
echo "alias k='kubectl'" >> ~/.bashrc

# 使设置失效
source ~/.bashrc

配置主动补全

yum install -y bash-completion

source <(kubectl completion bash)

echo "source <(kubectl completion bash)" >> ~/.bashrc

source ~/.bashrc

验证装置

k get cs
---------------------------------------------------------
NAME                 STATUS    MESSAGE             ERROR
etcd-1               Healthy   {"health":"true"}   
scheduler            Healthy   ok                  
controller-manager   Healthy   ok                  
etcd-2               Healthy   {"health":"true"}   
etcd-0               Healthy   {"health":"true"}   

k get node
---------------------------------------------------------------------
NAME             STATUS                     ROLES    AGE     VERSION
192.168.64.191   Ready,SchedulingDisabled   master   5d23h   v1.15.2
192.168.64.192   Ready                      node     5d23h   v1.15.2
192.168.64.193   Ready                      node     5d23h   v1.15.2

初步尝试 kubernetes

kubectl run 命令是最简略的部署援用的形式, 它主动创立必要组件, 这样, 咱们就先不用深刻理解每个组件的构造

应用 ReplicationController 和 pod 部署利用

Pod 是用来封装 Docker 容器的对象, 它具备本人的虚拟环境(端口, 环境变量等), 一个 Pod 能够封装多个 Docker 容器.

RC 是用来自动控制 Pod 部署的工具, 它能够主动启停 Pod, 对 Pod 进行主动伸缩.

上面咱们用命令部署一个 RC

cd ~/

k run 
    --image=luksa/kubia 
    --port=8080 
    --generator=run/v1 kubia

k get rc
---------------------------------------
NAME    DESIRED   CURRENT   READY   AGE
kubia   1         1         1       24s

k get pods
----------------------------------------------
NAME          READY   STATUS    RESTARTS   AGE
kubia-9z6kt   1/1     Running   0          28s

kubectl run 几个参数的含意

  • --image=luksa/kubia

    • 镜像名称
  • --port=8080

    • pod 对外裸露的端口
  • --generator=run/v1 kubia

    • 创立一个 ReplicationController

应用 service 对外裸露 pod

k expose 
    rc kubia 
    --type=NodePort 
    --name kubia-http

k get svc
------------------------------------------------------------------------------
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubia-http   NodePort    10.68.194.195   <none>        8080:20916/TCP   4s

这里创立了一个 service 组件, 用来对外裸露 pod 拜访, 在所有节点服务器上, 裸露了 20916 端口, 通过此端口, 能够拜访指定 pod 的 8080 端口

拜访以下节点服务器的 20916 端口, 都能够拜访该利用

留神: 要把端口批改成你生成的随机端口

  • http://192.168.64.191:20916/
  • http://192.168.64.192:20916/
  • http://192.168.64.193:20916/

pod 主动伸缩

k8s 对利用部署节点的主动伸缩能力十分强, 只须要指定须要运行多少个 pod,k8s 就能够实现 pod 的主动伸缩

# 将 pod 数量减少到 3 个
k scale rc kubia --replicas=3

k get po -o wide
----------------------------------------------------------------------------------------------------------------
NAME          READY   STATUS    RESTARTS   AGE   IP            NODE             NOMINATED NODE   READINESS GATES
kubia-q7bg5   1/1     Running   0          10s   172.20.3.29   192.168.64.193   <none>           <none>
kubia-qkcqh   1/1     Running   0          10s   172.20.2.30   192.168.64.192   <none>           <none>
kubia-zlmsn   1/1     Running   0          16m   172.20.3.28   192.168.64.193   <none>           <none>

# 将 pod 数量缩小到 1 个
k scale rc kubia --replicas=1

# k8s 会主动进行两个 pod, 最终 pod 列表中会只有一个 pod
k get po -o wide
---------------------------------------------------------------------------------------------------------------------
NAME          READY   STATUS        RESTARTS   AGE    IP            NODE             NOMINATED NODE   READINESS GATES
kubia-q7bg5   1/1     Terminating   0          6m1s   172.20.3.29   192.168.64.193   <none>           <none>
kubia-qkcqh   1/1     Terminating   0          6m1s   172.20.2.30   192.168.64.192   <none>           <none>
kubia-zlmsn   1/1     Running       0          22m    172.20.3.28   192.168.64.193   <none

pod

应用部署文件手动部署 pod

创立 kubia-manual.yml 部署文件

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

k create -f kubia-manual.yml

k get po
-----------------------------------------------
NAME           READY   STATUS    RESTARTS   AGE
kubia-manual   1/1     Running   0          19s

查看 pod 的部署文件

# 查看 pod 的部署文件
k get po kubia-manual -o yaml

查看 pod 日志

k logs kubia-manual

pod 端口转发

应用 kubectl port-forward 命令设置端口转发, 对外裸露 pod.

应用服务器的 8888 端口, 映射到 pod 的 8080 端口

k port-forward kubia-manual --address localhost,192.168.64.191 8888:8080

# 或在所有网卡上裸露 8888 端口
k port-forward kubia-manual --address 0.0.0.0 8888:8080

在浏览器中拜访 http://192.168.64.191:8888/

pod 标签

能够为 pod 指定标签, 通过标签能够对 pod 进行分组治理

ReplicationController,ReplicationSet,Service 中, 都能够通过 Label 来分组治理 pod

创立 pod 时指定标签

通过 kubia-manual-with-labels.yml 部署文件部署 pod

在部署文件中为 pod 设置了两个自定义标签:creation_methodenv

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: Never
    ports:                      # 容器裸露的端口
    - containerPort: 8080
      protocol: 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          10s    creation_method=manual,env=prod 

以列的模式列出 pod 的标签

k get po -L creation_method,env
-----------------------------------------------------------------------------
NAME              READY   STATUS    RESTARTS   AGE     CREATION_METHOD   ENV
kubia-5rz9h       1/1     Running   0          4m19s                     
kubia-manual      1/1     Running   0          3m22s                     
kubia-manual-v2   1/1     Running   0          2m40s   manual            prod

批改 pod 的标签

pod kubia-manual-v2 的 env 标签值是prod, 咱们把这个标签的值批改为 debug

批改一个标签的值时, 必须指定 --overwrite 参数, 目标是避免误批改

k label po kubia-manual-v2 env=debug --overwrite

k 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 查问
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 的 pod

# -l 查问
k get po 
    -l creation_method=manual,env=debug 
    -L creation_method,env
---------------------------------------------------------------------------
NAME              READY   STATUS    RESTARTS   AGE   CREATION_METHOD   ENV
kubia-manual      1/1     Running   0          33m   manual            debug
kubia-manual-v2   1/1     Running   0          32m   manual            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

其余查问举例:

  • creation_method!=manual
  • env in (prod,debug)
  • env notin (prod,debug)

把 pod 部署到指定的节点服务器

咱们不能间接指定服务器的地址来束缚 pod 部署的节点

通过为 node 设置标签, 在部署 pod 时, 应用节点选择器, 来抉择把 pod 部署到匹配的节点服务器

上面为名称为 192.168.64.193 的节点服务器, 增加标签gpu=true

k label node 
    192.168.64.193 
    gpu=true

k get node 
    -l gpu=true 
    -L gpu
------------------------------------------------------
NAME             STATUS   ROLES   AGE   VERSION   GPU
192.168.64.193   Ready    node    14d   v1.15.2   true

部署文件, 其中节点选择器 nodeSelector 设置了通过标签 gpu=true 来抉择节点

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.yml

k 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 

查看 pod kubia-gpu的形容

k describe po kubia-gpu
------------------------------------------------
Name:         kubia-gpu
Namespace:    default
Priority:     0
Node:         192.168.64.193/192.168.64.193
......

pod 注解

能够为资源增加注解

注解不能被选择器应用

# 注解
k annotate pod kubia-manual tedu.cn/shuoming="foo bar"

k describe po kubia-manual

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: Never
    livenessProbe:                   # 存活探针配置
      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 --previous
-----------------------------------------
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:  6
    Liveness:       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-unhealthy
    name: kubia
    imagePullPolicy: Never
    livenessProbe:
      httpGet:
        path: /
        port: 8080
      initialDelaySeconds: 15        # 第一次探测的延迟时间
EOF

控制器

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 治理的 pod
    app: kubia                     # 抉择标签 'app=kubia' 的 pod, 由以后 RC 进行治理
  template:                        # pod 模板, 用来创立新的 pod
    metadata:
      labels:
        app: kubia                 # 指定 pod 的标签
    spec:
      containers:                  # 容器配置
      - name: kubia                # 容器名
        image: luksa/kubia         # 镜像
        imagePullPolicy: Never
        ports:
        - 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

k 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

RC 是通过指定的标签 app=kubia 对匹配的 pod 进行治理的

容许在 pod 上增加任何其余标签, 而不会影响 pod 与 RC 的关联关系

k label pod kubia-fmtkw type=special

k 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 --overwrite

k 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: 3
  selector:
    app: kubia
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: kubia
        foo: 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 个 pod
  selector:
    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" 的 pod
  template:
    metadata:
      labels:
        app: kubia               # 为创立的 pod 增加标签 "app=kubia"
    spec:
      containers:
      - name: kubia              # 容器名
        image: luksa/kubia       # 镜像
        imagePullPolicy: Never
EOF

创立 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: 4
  selector:
    matchExpressions:       # 表达式匹配选择器
      - key: app            # label 名是 app
        operator: In        # in 运算符
        values:             # label 值列表
          - kubia
          - foo
  template:
    metadata:
      labels:
        app: kubia
    spec:
      containers:
      - name: kubia
        image: luksa/kubia
        imagePullPolicy: Never
EOF
# 先删除现有 RS
k delete rs kubia --cascade=false

# 再创立 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 kubia

k 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.yml

k 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   <n

能够在所有选定的节点上部署 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 ds

k get po

为节点’192.168.64.192’设置标签 disk=ssd

这样 DS 会在该节点上立刻创立 pod

k label node 192.168.64.192 disk=ssd

k get ds
---------------------------------------------------------------------------------------
NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
ssd-monitor   1         1         0       1            0           disk=ssd        37m

k 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.64.193’设置标签 disk=ssd

k label node 192.168.64.193 disk=ssd
k get ds
k get po -o wide

删除’192.168.64.193’节点上的 disk 标签, 那么该节点中部署的 pod 会被立刻销毁

# 留神删除格局: disk-
k label node 192.168.64.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.yml

k get job
-----------------------------------------
NAME        COMPLETIONS   DURATION   AGE
batch-job   0/1                      7s

k 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       2m16s


k 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-job
    spec:
      restartPolicy: OnFailure
      containers:
        - name: main
          image: luksa/batch-job
          imagePullPolicy: 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-job
    spec:
      restartPolicy: OnFailure
      containers:
        - name: main
          image: luksa/batch-job
          imagePullPolicy: 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-job
        spec:
          restartPolicy: OnFailure
          containers: 
          - name: main
            image: luksa/batch-job
            imagePullPolicy: 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

Service

通过 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.yml

k get svc
--------------------------------------------------------------------
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   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

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        # 回话亲和性应用 ClientIP
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: kubia
EOF
k create -f kubia-svc-clientip.yml

k get svc
------------------------------------------------------------------------
NAME             TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   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

在 pod 中, 能够通过一个环境变量来获知 Service 的 ip 地址

该环境变量在旧的 pod 中是不存在的, 咱们须要先删除旧的 pod, 用新的 pod 来代替

k delete po --all

k get po
-----------------------------------------------
NAME          READY   STATUS    RESTARTS   AGE
kubia-k66lz   1/1     Running   0          64s
kubia-vfcqv   1/1     Running   0          63s
kubia-z257h   1/1     Running   0          63s
k exec kubia-k66lz env
------------------------------------------------------------------
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=kubia-k66lz
KUBIA_SERVICE_PORT=80                             # kubia 服务的端口
KUBIA_PORT=tcp://10.68.163.98:80
KUBIA_CLIENTIP_SERVICE_PORT=80                    # kubia-clientip 服务的端口
KUBIA_CLIENTIP_PORT_80_TCP=tcp://10.68.72.120:80
KUBIA_CLIENTIP_PORT_80_TCP_PROTO=tcp
KUBERNETES_SERVICE_HOST=10.68.0.1
KUBERNETES_PORT_443_TCP=tcp://10.68.0.1:443
KUBIA_SERVICE_HOST=10.68.163.98                   # kubia 服务的 ip
KUBIA_CLIENTIP_SERVICE_HOST=10.68.72.120          # kubia-clientip 服务的 ip
......

通过 全限定域名 来拜访 Service

# 进入一个容器
k exec -it kubia-k66lz bash

ping kubia
curl http://kubia
curl http://kubia.default
curl http://kubia.default.svc.cluster.local

endpoint

endpoint 是在 Service 和 pod 之间的一种资源

一个 endpoint 资源, 蕴含一组 pod 的地址列表

# 查看 kubia 服务的 endpoint
k describe svc kubia
------------------------------
......
Endpoints:         172.20.2.40:8080,172.20.3.57:8080,172.20.3.58:8080
......

# 查看所有 endpoint
k get ep
--------------------------------------------------------------------------
NAME             ENDPOINTS                                            AGE
kubia            172.20.2.40:8080,172.20.3.57:8080,172.20.3.58:8080   95m
kubia-clientip   172.20.2.40:8080,172.20.3.57:8080,172.20.3.58:8080   59m

# 查看名为 kubia 的 endpoint
k get ep kubia

不含 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.yml
# 进入一个 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: ExternalName
  externalName: 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

在每个节点(包含 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.yml

k get svc kubia-nodeport
-----------------------------------------------------------------------------
NAME             TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubia-nodeport   NodePort   10.68.140.119   <none>        80:30123/TCP   14m

能够通过任意节点的 30123 端口来拜访 Service

  • http://192.168.64.191:30123
  • http://192.168.64.192:30123
  • http://192.168.64.193:30123

磁盘挂载到容器


卷的类型:

  • emptyDir: 简略的空目录
  • hostPath: 工作节点中的磁盘门路
  • gitRepo: 从 git 克隆的本地仓库
  • nfs: nfs 共享文件系统

创立蕴含两个容器的 pod, 它们共享同一个卷

cat <<EOF > fortune-pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: fortune
  labels:
    app: fortune
spec:
  containers:
  - image: luksa/fortune                 # 镜像名
    name: html-genrator                  # 容器名
    imagePullPolicy: Never
    volumeMounts:
    - name: html                         # 卷名为 html
      mountPath: /var/htdocs             # 容器中的挂载门路
  - image: nginx:alpine                  # 第二个镜像名
    name: web-server                     # 第二个容器名
    imagePullPolicy: Never
    volumeMounts:
    - name: html                         # 雷同的卷 html
      mountPath: /usr/share/nginx/html   # 在第二个容器中的挂载门路
      readOnly: true                     # 设置为只读
    ports:
    - containerPort: 80
      protocol: TCP
  volumes:                               # 卷
  - name: html                           # 为卷命名
    emptyDir: {}                         # emptyDir 类型的卷
EOF
k create -f fortune-pod.yml

k get po

创立 Service, 通过这个 Service 拜访 pod 的 80 端口

cat <<EOF > fortune-svc.yml
apiVersion: v1
kind: Service
metadata:
  name: fortune
spec:
  type: NodePort
  ports:
  - port: 8088
    targetPort: 80
    nodePort: 38088
  selector:
    app: fortune
EOF
k create -f fortune-svc.yml

k get svc

# 用浏览器拜访  http://192.168.64.191:38088/

NFS 文件系统

在 master 节点 192.168.64.191 上创立 nfs 目录 /etc/nfs_data,
并容许 1921.68.64 网段的主机共享拜访这个目录

# 创立文件夹
mkdir /etc/nfs_data

# 在 exports 文件夹中写入配置
# no_root_squash: 服务器端应用 root 权限
cat <<EOF > /etc/exports
/etc/nfs_data    192.168.64.0/24(rw,async,no_root_squash)
EOF
systemctl enable nfs
systemctl enable rpcbind
systemctl start nfs
systemctl start rpcbind

尝试在客户端主机上, 例如 192.168.64.192, 挂载近程的 nfs 目录

# 新建挂载目录
mkdir /etc/web_dir/

# 在客户端, 挂载服务器的 nfs 目录
mount -t nfs 192.168.64.191:/etc/nfs_data /etc/web_dir/

长久化存储

创立 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_data
    server: 192.168.64.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.yml

k get pvc
-----------------------------------------------------------------------------------
NAME          STATUS   VOLUME       CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mongodb-pvc   Bound    mongodb-pv   1Gi        RWO,ROX                       3s

cat <<EOF > mongodb-pod-pvc.yml
apiVersion: v1
kind: Pod
metadata:
  name: mongodb
spec:
  containers:
  - image: mongo
    name: mongodb
    imagePullPolicy: Never
    securityContext:
      runAsUser: 0
    volumeMounts:
    - name: mongodb-data
      mountPath: /data/db
    ports:
    - containerPort: 27017
      protocol: TCP
  volumes:
  - name: mongodb-data
    persistentVolumeClaim:
      claimName: mongodb-pvc     # 援用之前创立的 "长久卷申明"
EOF

验证 pod 中加挂载了 nfs 近程目录作为长久卷

k create -f mongodb-pod-pvc.yml

k exec -it mongodb mongo

use mystore
db.foo.insert({name:'foo'})
db.foo.find()

查看在 nfs 近程目录中的文件

cd /etc/nfs_data
ls

配置启动参数

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 的 ENTRYPOINTCMD

  • 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: fortune
  labels:
    app: fortune
spec:
  containers:

  - image: luksa/fortune:args
    args: ["2"]                  # docker 镜像中配置的 CMD 是 10, 这里用 args 把这个值笼罩成 2
    name: html-genrator
    imagePullPolicy: Never
    volumeMounts:
    - name: html
      mountPath: /var/htdocs

  - image: nginx:alpine
    name: web-server
    imagePullPolicy: Never
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      readOnly: true
    ports:
    - containerPort: 80
      protocol: TCP

  volumes:
  - name: html
    emptyDir: {}
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.64.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: fortune
  labels:
    app: fortune
spec:
  containers:

  - image: luksa/fortune:env
    env:                        # 设置环境变量 INTERVAL=5
    - name: INTERVAL
      value: "5"
    name: html-genrator
    imagePullPolicy: Never
    volumeMounts:
    - name: html
      mountPath: /var/htdocs

  - image: nginx:alpine
    name: web-server
    imagePullPolicy: Never
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      readOnly: true
    ports:
    - containerPort: 80
      protocol: TCP

  volumes:
  - name: html
    emptyDir: {}
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: fortune
labels:

app: fortune

spec:
containers:

  • image: luksa/fortune:env
    imagePullPolicy: Never
    env:

    • name: INTERVAL # 环境变量名
      valueFrom:

      configMapKeyRef:          # 环境变量的值从 ConfigMap 获取
        name: fortune-config    # 应用的 ConfigMap 名称
        key: sleep-interval     # 用指定的键从 ConfigMap 取数据

    name: html-genrator
    volumeMounts:

    • name: html
      mountPath: /var/htdocs
  • image: nginx:alpine
    imagePullPolicy: Never
    name: web-server
    volumeMounts:

    • name: html
      mountPath: /usr/share/nginx/html
      readOnly: true

    ports:

    • containerPort: 80
      protocol: TCP

volumes:

  • name: html
    emptyDir: {}

EOF

config-map–>env–>arg

配置环境变量后, 能够在启动参数中应用环境变量

cat <<EOF > fortune-pod-args.yml
apiVersion: v1
kind: Pod
metadata:
  name: fortune
  labels:
    app: fortune
spec:
  containers:

  - image: luksa/fortune:args
    imagePullPolicy: Never
    env:
    - name: INTERVAL
      valueFrom:
        configMapKeyRef:
          name: fortune-config
          key: sleep-interval
    args: ["$(INTERVAL)"]        # 启动参数中应用环境变量
    name: html-genrator
    volumeMounts:
    - name: html
      mountPath: /var/htdocs

  - image: nginx:alpine
    imagePullPolicy: Never 
    name: web-server
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      readOnly: true
    ports:
    - containerPort: 80
      protocol: TCP

  volumes:
  - name: html
    emptyDir: {}
EOF

从磁盘文件创建 ConfigMap
先删除之前创立的 ComfigMap

d delete cm fortune-config

创立一个文件夹, 寄存配置文件

cd ~/
mkdir configmap-files
cd configmap

创立 nginx 的配置文件, 启用对文本文件和 xml 文件的压缩

cat <<EOF > my-nginx-config.conf
server {
    listen           80;
    server_name      www.kubia-example.com;
    
    gzip             on;
    gzip_types       text/plain application/xml;
    
    location / {
        root         /ur/share/nginx/html;
        index        index.html index.htm;
    }
}
EOF

增加 sleep-interval 文件, 写入值 25

cat <<EOF > sleep-interval
25
EOF

从 configmap-files 文件夹创立 ConfigMap

cd ~/

k create configmap fortune-config 
--from-file=configmap-files 

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: 3
  selector: 
    matchLabels:
      app: kubia
  template:
    metadata:
      name: kubia
      labels:
        app: kubia
    spec:
      containers:
      - image: luksa/kubia:v1
        imagePullPolicy: Never
        name: nodejs
EOF
k create -f kubia-deployment-v1.yml --record

k get deploy
-----------------------------------------------
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
kubia   3/3     3            3           2m35s

k get rs
----------------------------------------------------
NAME               DESIRED   CURRENT   READY   AGE
kubia-66b4657d7b   3         3         3       3m4s

k 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          3m12s

k rollout status deploy kubia
------------------------------------------
deployment "kubia" successfully rolled out

rs 和 pod 名称中的数字, 是 pod 模板的哈希值

降级 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.64.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 处于不可用状态.
    如果冀望 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: 3
  selector: 
    matchLabels:
      app: kubia
  minReadySeconds: 10
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      name: kubia
      labels:
        app: kubia
    spec:
      containers:
      - image: luksa/kubia:v3
        name: nodejs
        imagePullPolicy: Never
        readinessProbe:
          periodSeconds: 1
          httpGet:
            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    MinimumReplicasAvailable
  Progressing    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}')

正文完
 0