目录
3、ReplicaSet控制器示例——容器数量检测(容器挂掉时自动创建)
5、DaemonSet控制器示例——确保全部(或者某些)节点上运行一个 Pod 的副本
6、Job控制器示例——执行批处理任务,仅执行一次任务,做完以后就退出了
7、Cronjob控制器示例——CronJob创建定时任务,周期性地在给定的调度时间执行Job
6、第二种从外部访问 Service 的方式LoadBalancer 类型的 Service
8、第三种从外部访问service的方式ExternalName
一、Kubernetes简介
1、Kubernetes简介
2、kubernetes设计架构
Kubernetes集群包含有节点代理kubelet和Master组件(APIs, scheduler, etc),一切都基于分布式的存储系统。
3、Kubernetes核心组件
Kubernetes主要由以下几个核心组件组成:
etcd | 保存了整个集群的状态 |
apiserver | 提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制 |
controller manager | 负责维护集群的状态,比如故障检测、自动扩展、滚动更新等 |
scheduler | 负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上 |
kubelet | 负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理 |
Container runtime | 负责镜像管理以及Pod和容器的真正运行(CRI) |
kube-proxy | 负责为Service提供cluster内部的服务发现和负载均衡 |
除了核心组件,还有一些推荐的Add-ons:
kube-dns | 负责为整个集群提供DNS服务 |
Ingress Controller | 为服务提供外网入口 |
Heapster | 提供资源监控 |
Dashboard | 提供GUI |
Federation | 提供跨可用区的集群 |
Fluentd-elasticsearch | 提供集群日志采集、存储与查询 |
4、kubernetes设计结构
Kubernetes设计理念和功能其实就是一个类似Linux的分层架构
二、Kubernetes部署
1、官方文档:
Container runtimes | KubernetesYou need to install a container runtime into each node in the cluster so that Pods can run there. This page outlines what is involved and describes related tasks for setting up nodes.Kubernetes 1.23 requires that you use a runtime that conforms with the Container Runtime Interface (CRI).See CRI version support for more information.This page lists details for using several common container runtimes with Kubernetes, on Linux:https://kubernetes.io/docs/setup/production-environment/container-runtimes/#docker准备工作:本实验以server1为harbor仓库,在server2、server3、server4三台虚拟机上部署k8s,server2作为管理节点。
在server2、server3、server4上重置docker
300 systemctl status docker
301 rm -f /etc/systemd/system/docker.service.d/10-machine.conf
302 systemctl daemon-reload
303 systemctl restart docker.service
304 systemctl restart docker.socket
305 docker info
在server1上清空docker-machine节点
[root@server1 harbor]# docker-machine rm server4
About to remove server4
WARNING: This action will delete both local reference and remote instance.
Are you sure? (y/n): y
Successfully removed server4
[root@server1 harbor]# docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
2、使用部署工具kubeadm安装Kubernetes
安装 kubeadm | KubernetesThis page shows how to install the `kubeadm` toolbox. For information on how to create a cluster with kubeadm once you have performed this installation process, see the [Using kubeadm to Create a Cluster](/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/) page. -- 本页面显示如何安装 kubeadm 工具箱。 有关在执行此安装过程后如何使用 kubeadm 创建集群的信息,请参见 使用 kubeadm 创建集群 页面。准备开始 一台兼容的 Linux 主机。Kubernetes 项目为基于 Debian 和 Red Hat 的 Linux 发行版以及一些不提供包管理器的发行版提供通用的指令 每台机器 2 GB 或更多的 RAM (如果少于这个数字将会影响你应用的运行内存) 2 CPU 核或更多 集群中的所有机器的网络彼此均能相互连接(公网和内网都可以) 节点之中不可以有重复的主机名、MAC 地址或 product_uuid。请参见这里了解更多详细信息。 开启机器上的某些端口。请参见这里 了解更多详细信息。 禁用交换分区。为了保证 kubelet 正常工作,你 必须 禁用交换分区。 确保每个节点上 MAC 地址和 product_uuid 的唯一性 你可以使用命令 ip link 或 ifconfig -a 来获取网络接口的 MAC 地址 可以使用 sudo cat /sys/class/dmi/id/product_uuid 命令对 product_uuid 校验 一般来讲,硬件设备会拥有唯一的地址,但是有些虚拟机的地址可能会重复。 Kubernetes 使用这些值来唯一确定集群中的节点。 如果这些值在每个节点上不唯一,可能会导致安装 失败。https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/准备工作:设置cgroupdriver=systemd;禁用swap交换分区;允许iptables检查桥接流量
#在server2/3/4上更改引擎文件,设置cgroupdriver=systemd
[root@server2 ~]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://reg.westos.org"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
[root@server2 ~]# systemctl daemon-reload
[root@server2 ~]# systemctl restart docker
#在server2/3/4上禁用swap交换分区
[root@server2 ~]# swapoff -a
[root@server2 ~]# vim /etc/fstab
11 #/dev/mapper/rhel-swap swap swap defaults 0 0
#允许server2/3/4的iptables检查桥接流量
[root@server2 ~]# vim /etc/sysctl.d/docker.conf
[root@server2 ~]# cat /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
[root@server2 ~]# sysctl --system
安装软件:配置软件源并安装软件kubeadm、kubelet 和 kubectl
#在server2/3/4上配置阿里云的软件源,用于安装kubeadm
[root@server2 yum.repos.d]# vim /etc/yum.repos.d/k8s.repo
[root@server2 yum.repos.d]#
[root@server2 yum.repos.d]# cat /etc/yum.repos.d/k8s.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
#在server2/3/4上安装软件并激活及开机自启kubelet
[root@server2 yum.repos.d]# yum install -y kubeadm kubelet kubectl
[root@server2 yum.repos.d]# systemctl enable --now kubelet
部署Kubernetes
kubeadm config print init-defaults //查看默认配置信息
#在server1中删掉所有未使用的镜像
docker images |grep -v REPOSITORY |awk '{system("docker rmi "$1":"$2"")}'
#在server2中查询kubeadm所需镜像
[root@server2 yum.repos.d]# kubeadm config images list --image-repository registry.aliyuncs.com/google_containers
registry.aliyuncs.com/google_containers/kube-apiserver:v1.23.4
registry.aliyuncs.com/google_containers/kube-controller-manager:v1.23.4
registry.aliyuncs.com/google_containers/kube-scheduler:v1.23.4
registry.aliyuncs.com/google_containers/kube-proxy:v1.23.4
registry.aliyuncs.com/google_containers/pause:3.6
registry.aliyuncs.com/google_containers/etcd:3.5.1-0
registry.aliyuncs.com/google_containers/coredns:v1.8.6
#在server1中拉取所需镜像
1146 docker pull registry.aliyuncs.com/google_containers/kube-apiserver:v1.23.4
1147 docker pull registry.aliyuncs.com/google_containers/kube-controller-manager:v1.23.4
1148 docker pull registry.aliyuncs.com/google_containers/kube-scheduler:v1.23.4
1149 docker pull registry.aliyuncs.com/google_containers/kube-proxy:v1.23.4
1150 docker pull registry.aliyuncs.com/google_containers/pause:3.6
1151 docker pull registry.aliyuncs.com/google_containers/etcd:3.5.1-0
1152 docker pull registry.aliyuncs.com/google_containers/coredns:v1.8.6
在server1中修改镜像标签并上传到harbor私有仓库
#在server1中修改镜像标签
[root@server1 ~]# docker images | grep aliyuncs | awk '{print $1":"$2}' |awk -F/ '{system("docker tag "$0" reg.westos.org/k8s/"$3"")}'
#修改完成后如下所示:
[root@server1 ~]# docker images |grep k8s
reg.westos.org/k8s/kube-apiserver v1.23.4 62930710c963 4 days ago 135MB
reg.westos.org/k8s/kube-proxy v1.23.4 2114245ec4d6 4 days ago 112MB
reg.westos.org/k8s/kube-scheduler v1.23.4 aceacb6244f9 4 days ago 53.5MB
reg.westos.org/k8s/kube-controller-manager v1.23.4 25444908517a 4 days ago 125MB
reg.westos.org/k8s/etcd 3.5.1-0 25f8c7f3da61 3 months ago 293MB
reg.westos.org/k8s/coredns v1.8.6 a4ca41631cc7 4 months ago 46.8MB
reg.westos.org/k8s/pause 3.6 6270bb605e12 5 months ago 683kB
#在server1中将改标签后的镜像上传到harbor私有仓库
[root@server1 ~]# docker images |grep k8s | awk '{system("docker push "$1":"$2"")}'
在server2中查询本地私有harbor仓库的镜像并开始部署k8s集群
#在server2中查询私有harbor仓库的镜像
[root@server2 ~]# kubeadm config images list --image-repository reg.westos.org/k8s
#在server2中拉取私有harbor仓库的镜像
[root@server2 ~]# kubeadm config images pull --image-repository reg.westos.org/k8s
#在server2中初始化集群
[root@server2 ~]# kubeadm init --pod-network-cidr=10.244.0.0/16 --image-repository reg.westos.org/k8s
#执行授权(每次重启系统都要执行,或者直接放到.bash_profile中开机自动执行)
[root@server2 ~]# export KUBECONFIG=/etc/kubernetes/admin.conf
[root@server2 ~]# vim .bash_profile
[root@server2 ~]# cat .bash_profile
export KUBECONFIG=/etc/kubernetes/admin.conf
#Master查看状态
[root@server2 ~]# kubectl get pod --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-7b56f6bc55-6httc 0/1 Pending 0 6m10s
kube-system coredns-7b56f6bc55-k5fnm 0/1 Pending 0 6m10s
kube-system etcd-server2 1/1 Running 0 6m24s
kube-system kube-apiserver-server2 1/1 Running 0 6m26s
kube-system kube-controller-manager-server2 1/1 Running 0 6m24s
kube-system kube-proxy-5rgqp 1/1 Running 0 6m11s
kube-system kube-scheduler-server2 1/1 Running 0 6m24s
3、安装flannel网络组件
GitHub - flannel-io/flannel: flannel is a network fabric for containers, designed for Kuberneteshttps://github.com/coreos/flannel
#在server2上下载flannel插件
[root@server2 ~]# wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
从此文件中搜索“/image”得到两个镜像,在server1中拉取镜像,并上传到harbor仓库
#拉取镜像
1160 docker pull rancher/mirrored-flannelcni-flannel-cni-plugin:v1.0.1
1161 docker pull rancher/mirrored-flannelcni-flannel:v0.16.3
#更改镜像标签
1162 docker tag rancher/mirrored-flannelcni-flannel-cni-plugin:v1.0.1 reg.westos.org/rancher/mirrored-flannelcni-flannel-cni-plugin:v1.0.1
1163 docker tag rancher/mirrored-flannelcni-flannel:v0.16.3 reg.westos.org/rancher/mirrored-flannelcni-flannel:v0.16.3
#上传镜像到harbor
1164 docker push reg.westos.org/rancher/mirrored-flannelcni-flannel-cni-plugin:v1.0.1
1165 docker push reg.westos.org/rancher/mirrored-flannelcni-flannel:v0.16.3
注意:需要提前在harbor仓库中创建“rancher”
#安装网络组件
[root@server2 ~]# kubectl apply -f kube-flannel.yml
(
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml)由于上一步已经从该网站下载好,所以可以直接安装
4、其他节点接入k8s集群
#在server3/4中执行此命令,加入server2管理的k8s集群
[root@server3 ~]# kubeadm join 172.25.254.2:6443 --token ksbiu3.b7inb9pr5iseanvs --discovery-token-ca-cert-hash sha256:44c18b0ff87e7ca592fa36d5057e2fe71459e1ce0f6df4c996deb4a12d180b5e
#在server2中查看k8s集群中的节点
[root@server2 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
server2 Ready control-plane,master 41m v1.23.4
server3 Ready <none> 22s v1.23.4
server4 Ready <none> 35s v1.23.4
#在server2中查看集群中所有容器状态都为“running”,则证明k8s集群部署成功
[root@server2 ~]# kubectl get pod --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-7b56f6bc55-6httc 1/1 Running 0 47m
kube-system coredns-7b56f6bc55-k5fnm 1/1 Running 0 47m
kube-system etcd-server2 1/1 Running 0 48m
kube-system kube-apiserver-server2 1/1 Running 0 48m
kube-system kube-controller-manager-server2 1/1 Running 0 48m
kube-system kube-flannel-ds-fdwcr 1/1 Running 0 17m
kube-system kube-flannel-ds-vkrd8 1/1 Running 0 7m1s
kube-system kube-flannel-ds-wp5x5 1/1 Running 0 6m47s
kube-system kube-proxy-5pvc7 1/1 Running 0 7m1s
kube-system kube-proxy-5rgqp 1/1 Running 0 47m
kube-system kube-proxy-lbglv 1/1 Running 0 6m47s
kube-system kube-scheduler-server2 1/1 Running 0 48m
Master查看状态:
kubectl get cs
kubectl get node
kubectl get pod -n kube-system -o wide
查看pod的具体信息
kubectl get pod -n kube-system -o wide #显示所有pod
kubectl describe pod kube-proxy-5pvc7 -n kube-system #显示kube-proxy-5pvc7的所有信息
kubectl logs kube-proxy-5pvc7 -n kube-system #显示kube-proxy-5pvc7日志
-n:指定namespace
#查看所有namespace
[root@server2 ~]# kubectl get ns
NAME STATUS AGE
default Active 3d4h
kube-node-lease Active 3d4h
kube-public Active 3d4h
kube-system Active 3d4h
#指定namespace
[root@server2 ~]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-7b56f6bc55-6httc 1/1 Running 1 (28m ago) 3d4h
coredns-7b56f6bc55-k5fnm 1/1 Running 1 (28m ago) 3d4h
etcd-server2 1/1 Running 1 (28m ago) 3d4h
kube-apiserver-server2 1/1 Running 1 (28m ago) 3d4h
kube-controller-manager-server2 1/1 Running 1 (28m ago) 3d4h
kube-flannel-ds-fdwcr 1/1 Running 1 (28m ago) 3d4h
kube-flannel-ds-vkrd8 1/1 Running 1 (28m ago) 3d3h
kube-flannel-ds-wp5x5 1/1 Running 1 (28m ago) 3d3h
三、Pod管理
1、pod的创建与删除
#创建并运行pod
kubectl run nginx --image=nginx #在当前namespace创建并运行nginx镜像
kubectl get pod -o wide #查看当前namespace中的镜像信息
#删除pod
kubectl delete pod nginx
注意:使用“kubectl run”命令创建pod时,是自主式的pod,删了就没了;使用“kubectl create deployment”命令创建pod时,会创建一个控制器用于管理此pod。
#在一个pod中同时创建多个container,pod名为my-dep
kubectl create deployment my-dep --image=myapp:v1 --replicas=3
#pod的删除,需要删除控制器
kubectl delete deployments.apps my-dep #删除控制器
kubectl delete svc my-dep #删除网络
[root@server2 ~]# kubectl expose deployment my-dep --port=80 --target-port=80
service/my-dep exposed
[root@server2 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d5h
my-dep ClusterIP 10.108.77.188 <none> 80/TCP 9s
2、pod中的端口暴露——service微服务
第一种从外部访问pod的方式:NodePort
#显示pod网络信息
[root@server2 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d5h
my-dep ClusterIP 10.108.77.188 <none> 80/TCP 36m
#编辑my-dep这个pod的网络,网络更改如下
[root@server2 ~]# kubectl edit svc my-dep
service/my-dep edited
#再次查看pod的网络信息
[root@server2 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d5h
my-dep NodePort 10.108.77.188 <none> 80:30212/TCP 37m
配置完成后在外部网络再次测试,测试时加上映射的端口。可以看到:访问集群中的任何节点都得到同样的结果。
2、Pod扩容与缩容
#pod扩容
kubectl scale --replicas=6 deployment my-dep
#pod缩容
kubectl scale --replicas=3 deployment my-dep
3、更新pod镜像
#更新pod镜像,从之前的myapp:v1更新到myapp:v2
kubectl set image deployment my-dep myapp=myapp:v2 --record
#查看my-dep的更新历史
kubectl rollout history deployment my-dep
在server2的master端更改完成后,外部网络访问时可以看到版本已经更新了
#pod版本回滚
kubectl rollout undo deployment my-dep --to-revision=1
pod版本回滚后,查看版本更新历史;查看当前pod信息;测试;均可以看到明显效果。
四、资源清单
yaml资源清单教程
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/
1、资源清单举例
#创建并运行一个pod
[root@server2 ~]# kubectl run demo --image=nginx
pod/demo created
#查看状态
[root@server2 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
demo 1/1 Running 0 10s
#将此pod输出为demo.yaml文件
[root@server2 ~]# kubectl get pod -o yaml > demo.yaml
#从yaml文件中创建pod
[root@server2 pod]# kubectl apply -f demo.yaml
pod/demo created
#删除pod
[root@server2 pod]# kubectl delete -f demo.yaml
pod "demo" deleted
#查看pod信息
[root@server2 pod]# kubectl describe pod demo
#显示节点标签
[root@server2 pod]# kubectl get nodes --show-labels
#进入交互式容器,demo表示pod名称,busybox表示容器名称,-it表示前台运行
[root@server2 pod]# kubectl attach demo -c busybox -it
If you don't see a command prompt, try pressing enter.
/ # ip addr
2、资源清单中的参数详情
3、资源清单示例:
[root@server2 pod]# vim demo.yaml
1 apiVersion: v1
2 kind: Pod
3 metadata:
4 name: demo
5 spec:
6 containers:
7 - name: myapp #创建第一个容器,容器名为myapp
8 image: myapp:v1
9 imagePullPolicy: IfNotPresent
10 ports:
11 - name: http
12 containerPort: 80 #容器内端口
13 hostPort: 80 #宿主机端口
14 resources: #设置资源上限,容器可从节点上分配到的上限
15 limits:
16 cpu: 1
17 memory: 200Mi
18 requests: #设置资源下限,如果节点不符合要求则无法运行
19 cpu: 0.5
20 memory: 100Mi
21 - name: busybox #创建第二个容器,名为busybox
22 image: busyboxplus
23 imagePullPolicy: IfNotPresent
24 stdin: true #应用型容器需要给他一个终端
25 tty: true #这两项都是设置终端
26
27
28 nodeSelector: #指定运行的节点
29 kubernetes.io/hostname: server3
30 hostNetwork: true #默认为false,设置为true表示使用主机网络,类似于docker中的host模式
五、Pod生命周期
1、Pod生命周期结构图
2、Pod的生命周期官方文档
Pod 的生命周期 | Kubernetes本页面讲述 Pod 的生命周期。 Pod 遵循一个预定义的生命周期,起始于 Pending 阶段,如果至少 其中有一个主要容器正常启动,则进入 Running,之后取决于 Pod 中是否有容器以 失败状态结束而进入 Succeeded 或者 Failed 阶段。在 Pod 运行期间,kubelet 能够重启容器以处理一些失效场景。 在 Pod 内部,Kubernetes 跟踪不同容器的状态 并确定使 Pod 重新变得健康所需要采取的动作。在 Kubernetes API 中,Pod 包含规约部分和实际状态部分。 Pod 对象的状态包含了一组 Pod 状况(Conditions)。 如果应用需要的话,你也可以向其中注入自定义的就绪性信息。Pod 在其生命周期中只会被调度一次。 一旦 Pod 被调度(分派)到某个节点,Pod 会一直在该节点运行,直到 Pod 停止或者 被终止。节点(Node) dies, the Pods scheduled to that node are [scheduled for deletion](#pod-garbage-collection) after a timeout period. -- Pod 生命期 和一个个独立的应用容器一样,Pod 也被认为是相对临时性(而不是长期存在)的实体。 Pod 会被创建、赋予一个唯一的 ID(UID), 并被调度到节点,并在终止(根据重启策略)或删除之前一直运行在该节点。https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/
3、Init 容器
4、init容器实例
注意:(1)只要yml剧本中存在定义init容器的语句,将会优先执行,无论书写顺序。(2)yml剧本中拉取的镜像会自动从本地仓库中拉取,本地仓库不存在才会去外网拉取,不指定版本的话默认是最新版
[root@server2 init]# vim init.yml
1 apiVersion: v1
2 kind: Pod
3 metadata:
4 name: nginx
5 labels:
6 app: nginx
7 spec:
8 containers:
9 - name: nginx
10 image: nginx
11 imagePullPolicy: IfNotPresent
12 initContainers:
13 - name: init-container
14 image: busybox
15 command: ["/bin/sh", "-c", "until nslookup myservice.default.svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
编写svc文件,pod名为“myservice”。编写完成后启动svc.yml。主容器nginx已经可以处于正常运行状态。主容器启动以后,初始化容器就已经停止了。
只要创建了svc,就会在集群中提供解析,svc停止后,解析也没有了!!!因此svc是为初始化容器准备的!!!
[root@server2 init]# vim svc.yml
1 apiVersion: v1
2 kind: Service
3 metadata:
4 name: myservice #端口随便设置,但是要设置好这个服务名称
5 spec:
6 ports:
7 - protocol: TCP
8 port: 80
9 targetPort: 80
测试svc解析:
方法一:
[root@server2 init]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d19h
myservice ClusterIP 10.101.15.64 <none> 80/TCP 17m
[root@server2 init]# kubectl run -it demo --image=busybox --restart=Never
If you don't see a command prompt, try pressing enter.
/ # nslookup myservice #第一次解析失败
Server: 10.96.0.10
Address: 10.96.0.10:53
** server can't find myservice.default.svc.cluster.local: NXDOMAIN
/ # nslookup myservice.default.svc.cluster.local. #第二次解析成功
Server: 10.96.0.10
Address: 10.96.0.10:53
Name: myservice.default.svc.cluster.local
Address: 10.101.15.64
方法二:
dig -t A myservice.default.svc.cluster.local. @10.96.0.10 #最后的IP地址表示service被集群分配到的IP
5、探针
配置存活、就绪和启动探测器 | Kuberneteshttps://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
6、存活探针和就绪探针实例
存活探针检测的是:镜像启动2秒后检测80端口是否可用,每隔3秒钟检测一次,每次检测时允许有1秒的超时时间
就绪探针检测的是:通过80端口检测默认发布目录下是否存在“test.html”文件,检测规则同上。检测通过后传达就绪指令。
[root@server2 init]# vim liveness.yml
1 apiVersion: v1
2 kind: Pod
3 metadata:
4 labels:
5 test: liveness
6 name: liveness-http
7 spec:
8 containers:
9 - name: liveness
10 image: nginx
11 imagePullPolicy: IfNotPresent
12 livenessProbe: #存活探针
13 tcpSocket:
14 port: 80
15 initialDelaySeconds: 2 #镜像启动延迟2秒后检测
16 periodSeconds: 3 #每隔3秒钟探测一次
17 timeoutSeconds: 1 #探测的超时时间
18 readinessProbe: #就绪探针
19 httpGet:
20 path: /test.html
21 port: 80
22 initialDelaySeconds: 2
23 periodSeconds: 3
24 timeoutSeconds: 1
创建一个svc.yml服务,用来暴露pod的端口。微服务通过标签来选择pod,用于向外界展示集群中的端口,当pod状态没有就绪之前,pod不会被微服务发现。微服务具有自动发现的功能,并实现后端的负载均衡。
[root@server2 init]# vim svc.yml
1 apiVersion: v1
2 kind: Service
3 metadata:
4 name: myservice
5 spec:
6 selector:
7 test: liveness
8 ports:
9 - protocol: TCP
10 port: 80 #服务端口
11 targetPort: 80 #pod/容器内端口
[root@server2 init]# kubectl exec -it liveness-http -- bash
六、控制器
1、控制器的基本概念
控制器类型的详细对比:
Replication Controller和ReplicaSet | ReplicaSet 是下一代的 Replication Controller,官方推荐使用ReplicaSet。 ReplicaSet 和 Replication Controller 的唯一区别是选择器的支持,ReplicaSet 支持新的基于集合的选择器需求。 ReplicaSet 确保任何时间都有指定数量的 Pod 副本在运行。 虽然 ReplicaSets 可以独立使用,但今天它主要被Deployments 用作协调 Pod 创建、删除和更新的机制。 |
Deployment | Deployment 为 Pod 和 ReplicaSet 提供了一个申明式的定义方法。 典型的应用场景: 用来创建Pod和ReplicaSet、 滚动更新和回滚、 扩容和缩容、 暂停与恢复 |
DaemonSet | DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。当有节点加入集群时, 也会为他们新增一个 Pod 。当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。 DaemonSet 的典型用法: 在每个节点上运行集群存储 DaemonSet,例如 glusterd、ceph。 在每个节点上运行日志收集 DaemonSet,例如 fluentd、logstash。 在每个节点上运行监控 DaemonSet,例如 Prometheus Node Exporter、zabbix agent等 一个简单的用法是在所有的节点上都启动一个 DaemonSet,将被作为每种类型的 daemon 使用。 一个稍微复杂的用法是单独对每种 daemon 类型使用多个 DaemonSet,但具有不同的标志, 并且对不同硬件类型具有不同的内存、CPU 要求。 |
StatefulSet | StatefulSet 是用来管理有状态应用的工作负载 API 对象。实例之间有不对等关系,以及实例对外部数据有依赖关系的应用,称为“有状态应用” StatefulSet 用来管理 Deployment 和扩展一组 Pod,并且能为这些 Pod 提供*序号和唯一性保证*。 StatefulSets 对于需要满足以下一个或多个需求的应用程序很有价值: 稳定的、唯一的网络标识符。 稳定的、持久的存储。 有序的、优雅的部署和缩放。 有序的、自动的滚动更新。 |
Job | 执行批处理任务,仅执行一次任务,保证任务的一个或多个Pod成功结束。 |
CronJob | Cron Job 创建基于时间调度的 Jobs。 一个 CronJob 对象就像 crontab (cron table) 文件中的一行,它用 Cron 格式进行编写,并周期性地在给定的调度时间执行 Job。 |
HPA | 根据资源利用率自动调整service中Pod数量,实现Pod水平自动缩放。 |
2、控制器的官方文档
工作负载资源 | Kuberneteshttps://kubernetes.io/zh/docs/concepts/workloads/controllers/
3、ReplicaSet控制器示例——容器数量检测(容器挂掉时自动创建)
[root@server2 pod]# vim rs.yml
1 apiVersion: apps/v1
2 kind: ReplicaSet #指定控制器类型
3 metadata:
4 name: replicaset-example
5 spec:
6 replicas: 3 #副本数为3(可随意扩容与缩容)
7 selector: #匹配标签
8 matchLabels:
9 app: nginx #匹配的标签为nginx
10 template: #template模板作用是将nginx标签应用到模板下的所有container
11 metadata:
12 labels:
13 app: nginx
14 spec: #定义容器
15 containers:
16 - name: nginx
17 image: nginx
#更改pod标签
[root@server2 pod]# kubectl label pod replicaset-example-8lwkf app=myapp --overwrite
#显示所有pod标签
[root@server2 pod]# kubectl get pod --show-labels
#显示rs控制器
[root@server2 pod]# kubectl get rs
4、Deployment控制器示例——版本回滚
[root@server2 pod]# vim deploy.yml
1 apiVersion: apps/v1
2 kind: Deployment #指定控制器类型
3 metadata:
4 name: deployment-nginx
5 spec:
6 replicas: 3
7 selector:
8 matchLabels:
9 app: nginx
10 template:
11 metadata:
12 labels:
13 app: nginx
14 spec:
15 containers:
16 - name: nginx
17 image: nginx:latest
Deployment控制器是在rs控制器基础之上建立的。基础功能同rs控制器一样,以container的标签为标准。更改container标签后,也会创建新的容器。
Deployment的主要功能是镜像版本的变更(升级或回滚)
更改镜像版本后,再次生效,会发现控制器后会有历史信息。
更改回之前的镜像版本,容器可以直接回滚为之前的版本!!!
Deployment的基本结构图如下所示:
当版本从v1变为v2时,会新建一个rs控制器,并通过v2的rs控制器创建新的容器,同时保留v1的rs控制器;版本要回滚到v1时,会直接从v1的rs控制器上创建容器,极大节省了资源。
5、DaemonSet控制器示例——确保全部(或者某些)节点上运行一个 Pod 的副本
[root@server2 pod]# vim ds.yml
1 apiVersion: apps/v1
2 kind: DaemonSet
3 metadata:
4 name: daemonset-example
5 labels:
6 k8s-app: zabbix-agent
7 spec:
8 selector:
9 matchLabels:
10 name: zabbix-agent
11 template:
12 metadata:
13 labels:
14 name: zabbix-agent
15 spec:
16 containers:
17 - name: zabbix-agent
18 image: nginx
这里不需要设置副本数量,它会自动为每个节点添加一个镜像。
6、Job控制器示例——执行批处理任务,仅执行一次任务,做完以后就退出了
[root@server2 pod]# vim job.yml
1 apiVersion: batch/v1
2 kind: Job #控制器类型
3 metadata:
4 name: pi
5 spec:
6 template:
7 spec:
8 containers:
9 - name: pi
10 image: perl #镜像名为perl
11 command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] #计算pi后2000位
12 restartPolicy: Never
13 backoffLimit: 4
#查看pod运行信息
[root@server2 pod]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
pi-d2r9p 0/1 ContainerCreating 0 11s
#通过logs查看运行结果
[root@server2 pod]# kubectl logs pi-d2r9p
7、Cronjob控制器示例——CronJob创建定时任务,周期性地在给定的调度时间执行Job
[root@server2 pod]# vim cronjob.yml
1 apiVersion: batch/v1beta1
2 kind: CronJob
3 metadata:
4 name: cronjob-example
5 spec:
6 schedule: "* * * * *" #“分时天月周”的时间执行job
7 jobTemplate:
8 spec:
9 template:
10 spec:
11 containers:
12 - name: cronjob
13 image: busybox
14 args:
15 - /bin/sh
16 - -c
17 - date; echo Hello from k8s cluster #每次通过busybox打印这句话
18 restartPolicy: OnFailure
每隔一分钟执行一次,输出一次语句。
七、service——微服务
1、Service概念
官方文档:
使用 Service 连接到应用 | Kuberneteshttps://kubernetes.io/zh/docs/concepts/services-networking/connect-applications-service/
开启kube-proxy的ipvs模式:
#所有节点安装ipvsadm管理器
yum install -y ipvsadm
#修改IPVS模式
kubectl edit cm kube-proxy -n kube-system
mode: "ipvs"
#更新kube-proxy pod
kubectl get pod -n kube-system |grep kube-proxy | awk '{system("kubectl delete pod "$1" -n kube-system")}'
更新完成后,通过ipvsadm看到策略已经更新,如下所示:
并且设置完成后,宿主机的网卡选项会多出来kube-ipvs的接口。所有增加的svc的地址都会增加到这个接口的IP上
2、deplyment控制器+svc服务
[root@server2 pod]# vim deploy.yml
1 apiVersion: apps/v1
2 kind: Deployment
3 metadata:
4 name: deployment-nginx
5 spec:
6 replicas: 3
7 selector:
8 matchLabels:
9 app: nginx
10 template:
11 metadata:
12 labels:
13 app: nginx
14 spec:
15 containers:
16 - name: nginx
17 image: myapp:v1
18 --- #创建微服务Service
19 apiVersion: v1
20 kind: Service
21 metadata:
22 name: myservice
23 spec:
24 selector:
25 app: nginx #注意标签和上边定义的deploy控制器的标签一致
26 ports:
27 - protocol: TCP
28 port: 80 #服务端口
29 targetPort: 80 #pod/容器内端口
通过ipvsadm查看转发规则,svc获取到的虚拟IP地址可以通过rr算法调度到后台的三个容器中。
八、k8s网络通信
1、Flannel vxlan模式跨主机通信原理
2、flannel网络
flannel网络原理:
3、flannel支持多种后端
配置flannel:
#配置flannel
[root@server2 ~]# kubectl edit cm -n kube-system kube-flannel-cfg
27 net-conf.json: |
28 {
29 "Network": "10.244.0.0/16",
30 "Backend": {
31 "Type": "host-gw" #由xvlan改为host-gw
32 }
33 }
#删除旧的flannel,控制器会按照新配置重新建立flannel
[root@server2 ~]# kubectl get pod -n kube-system |grep flannel | awk '{system("kubectl delete pod "$1" -n kube-system")}'
4、calico网络插件(详细信息在后边介绍)
calico网络架构:
5、Headless Service “无头服务”
Headless Service不需要分配一个VIP,而是直接以DNS记录的方式解析出被代理Pod的IP地址。 域名格式:$(servicename).$(namespace).svc.cluster.local
Headless Service实例:
[root@server2 service]# vim headless.yml
1 apiVersion: v1
2 kind: Service
3 metadata:
4 name: nginx-svc
5 spec:
6 ports:
7 - name: http
8 port: 80
9 targetPort: 80
10 selector:
11 app: nginx
12 clusterIP: None
6、第二种从外部访问 Service 的方式LoadBalancer 类型的 Service
从外部访问 Service 的第二种方式,适用于公有云上的 Kubernetes 服务。这时候,你可以指定一个 LoadBalancer 类型的 Service。(第一种是NodePort方式,第二种是LoadBalancer方式)
[root@server2 service]# vim lb.yml
1 apiVersion: v1
2 kind: Service
3 metadata:
4 name: lb-nginx
5 spec:
6 ports:
7 - name: http
8 port: 80
9 targetPort: 80
10 selector:
11 app: nginx
12 type: LoadBalancer
在service提交后,Kubernetes就会调用 CloudProvider 在公有云上为你创建一个负载均衡服务,并且把被代理的 Pod 的 IP地址配置给负载均衡服务做后端。在本例中的“EXTERNAL-IP”可以理解为一个负载均衡器。
基本结构图:
(1)云端环境如下:
(2)单机环境下:bare metal(裸金属方式)
7、在单机上部署Metallb-layer2环境
官方文档:
MetalLB, bare metal load-balancer for Kuberneteshttps://metallb.universe.tf/installation/
先启动一个svc服务,在其中添加了deployment控制器控制的nginx镜像,便于后续测试。
[root@server2 service]# vim lb.yml
1 apiVersion: v1
2 kind: Service
3 metadata:
4 name: lb-nginx
5 spec:
6 ports:
7 - name: http
8 port: 80
9 targetPort: 80
10 selector:
11 app: nginx
12 type: LoadBalancer
13
14 ---
15 apiVersion: apps/v1
16 kind: Deployment
17 metadata:
18 name: deployment-nginx
19 spec:
20 replicas: 3
21 selector:
22 matchLabels:
23 app: nginx
24 template:
25 metadata:
26 labels:
27 app: nginx
28 spec:
29 containers:
30 - name: nginx
31 image: myapp:v1
部署metallb-layer2
#设置ipvs模式
kubectl edit configmap -n kube-system kube-proxy
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
strictARP: true
#重新加载容器使更改生效
kubectl get pod -n kube-system |grep kube-proxy | awk '{system("kubectl delete pod "$1" -n kube-system")}
#安装新的namespace,并部署metallb
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml
注意:部署metallb时 ,metallb.yaml文件中会有拉取镜像,所以可以先将镜像下载到本地仓库中
#拉取镜像
[root@server1 ~]# docker pull quay.io/metallb/speaker:v0.12.1
[root@server1 ~]# docker pull quay.io/metallb/controller:v0.12.1
#更改镜像标签
[root@server1 ~]# docker tag quay.io/metallb/controller:v0.12.1 reg.westos.org/metallb/controller:v0.12.1
[root@server1 ~]# docker tag quay.io/metallb/speaker:v0.12.1 reg.westos.org/metallb/speaker:v0.12.1
#上传镜像
[root@server1 ~]# docker push reg.westos.org/metallb/controller:v0.12.1
[root@server1 ~]# docker push reg.westos.org/metallb/speaker:v0.12.1
#更改metallb.yaml的镜像获取地址
[root@server2 metallb]# vim metallb.yaml
365 image: metallb/speaker:v0.12.1
444 image: metallb/controller:v0.12.1
#运行metallb,并在指定的namespace中查看
[root@server2 metallb]# kubectl apply -f metallb.yaml
[root@server2 metallb]# kubectl get pod -n metallb-system
NAME READY STATUS RESTARTS AGE
controller-5764b9c97c-nqfpj 0/1 Running 0 14s
speaker-9fdrs 0/1 CreateContainerConfigError 0 15s
speaker-b97qz 0/1 CreateContainerConfigError 0 15s
speaker-dww54 0/1 CreateContainerConfigError 0 15s
配置地址池:
[root@server2 metallb]# vim config.yaml
1 apiVersion: v1
2 kind: ConfigMap
3 metadata:
4 namespace: metallb-system
5 name: config
6 data:
7 config: |
8 address-pools:
9 - name: default
10 protocol: layer2
11 addresses:
12 - 172.25.254.100-172.25.254.200 #设置为自己的IP地址池(要求外部可以访问)
测试:svc获得了一个“EXTERNAL-IP”后,外部网络就可以直接访问这个IP来访问后台的容器,并且访问是负载均衡的。测试结果如下
8、第三种从外部访问service的方式ExternalName
[root@server2 service]# vim ex-svc.yml
1 apiVersion: v1
2 kind: Service
3 metadata:
4 name: ex-service
5 spec:
6 type: ExternalName
7 externalName: test.westos.org
由于svc在集群内的IP地址总是在变化,因此可以提供一个解析使其相对固定下来;外部网络访问时只需要去找域名就可以自动解析到svc的IP。
也可以直接为svc绑定一个IP,svc启动后,需要手工向节点中加上一个IP地址,然后集群外部就可以访问,一般不推荐,这对后期的维护成本要求较高。
1 apiVersion: v1
2 kind: Service
3 metadata:
4 name: ex-service
5 spec:
6 selector:
7 app: nginx
8 ports:
9 - name: http
10 protocol: TCP
11 port: 80
12 targetPort: 80
13 externalIPs:
14 - 172.25.254.200
9、Ingress 服务——从外网访问集群内部
换言之:Ingress用来负载均衡svc,svc再去负载均衡pod
官方文档:
Installation Guide - NGINX Ingress Controllerhttps://kubernetes.github.io/ingress-nginx/deploy/#bare-metal-clusters
(1)基本ingress结构的部署步骤:
在server2中
#下载deploy.yml文件
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.1/deploy/static/provider/baremetal/deploy.yaml
在server1中拉取上面deply.yaml文件中需要的两个镜像,修改标签后上传到本地仓库
1044 docker pull liangjw/ingress-nginx-controller:v1.1.1
1045 docker pull liangjw/kube-webhook-certgen:v1.1.1
1046 docker tag liangjw/ingress-nginx-controller:v1.1.1 reg.westos.org/ingress-nginx/controller:v1.1.1
1047 docker tag liangjw/kube-webhook-certgen:v1.1.1 reg.westos.org/ingress-nginx/kube-webhook-certgen:v1.1.1
1048 docker push reg.westos.org/ingress-nginx/controller:v1.1.1
1049 docker push reg.westos.org/ingress-nginx/kube-webhook-certgen:v1.1.1
在server2中的deploy.yaml文件中镜像地址改为私有仓库的地址。
部署完成后效果如下:
基本逻辑是:client——>ingress——>svc——>pod。因此可以将ingress控制器改为LoadBalancer模式,会自动获取到一个IP地址,就可以从外部网络直接访问svc了。
先在的需求是,在外部主机访问“www1.westos.org”域名就可以通过ingress的方式访问到pod内部。因此需要重新设置一个svc
[root@server2 ingress]# cat ingress.yaml
1 apiVersion: networking.k8s.io/v1
2 kind: Ingress
3 metadata:
4 name: ingress-demo
5 spec:
6 ingressClassName: nginx
7 rules:
8 - host: www1.westos.org
9 http:
10 paths:
11 - path: / #直接访问根目录
12 pathType: Prefix
13 backend: #设置后端的svc
14 service:
15 name: myservice #后端的svc名称,必须匹配
16 port:
17 number: 80
#ingress.yml文件生效后,查看详细信息
[root@server2 ingress]# kubectl apply -f ingress.yaml
ingress.networking.k8s.io/ingress-demo created
[root@server2 ingress]# kubectl get ingress
下图绿框中表明,当外部网络访问“www1.westos.org”时,会自动访问后端“myservice:80”上的3个pod
在外部主机测试:
(2)ingress部署扩展——基于域名的虚拟主机
Ingress | KubernetesFEATURE STATE: Kubernetes v1.19 [stable] An API object that manages external access to the services in a cluster, typically HTTP. aka: tags: - networking - architecture - extension --- -- Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。术语 为了表达更加清晰,本指南定义了以下术语:服务(Service) that identifies a set of Pods using label selectors. Unless mentioned otherwise, Services are assumed to have virtual IPs only routable within the cluster network. -- 节点(Node): Kubernetes 集群中其中一台工作机器,是集群的一部分。 集群(Cluster): 一组运行由 Kubernetes 管理的容器化应用程序的节点。 在此示例和在大多数常见的 Kubernetes 部署环境中,集群中的节点都不在公共网络中。 边缘路由器(Edge router): 在集群中强制执行防火墙策略的路由器(router)。 可以是由云提供商管理的网关,也可以是物理硬件。 集群网络(Cluster network): 一组逻辑的或物理的连接,根据 Kubernetes 网络模型 在集群内实现通信。 服务(Service):Kubernetes 服务使用 标签选择算符(selectors)标识的一组 Pod。 除非另有说明,否则假定服务只具有在集群网络中可路由的虚拟 IP。 services within the cluster.https://kubernetes.io/zh/docs/concepts/services-networking/ingress/
为了和一步实验稍作区分,这里新建一个实验域名为“www2.westos.org”,并且svc服务名称为“myapp-svc”。
#新建svc服务
[root@server2 pod]# vim deploy-2.yml
1 apiVersion: apps/v1
2 kind: Deployment
3 metadata:
4 name: deployment-myapp
5 spec:
6 replicas: 3
7 selector:
8 matchLabels:
9 app: myapp
10 template:
11 metadata:
12 labels:
13 app: myapp
14 spec:
15 containers:
16 - name: myapp
17 image: myapp:v2
18 ---
19 apiVersion: v1
20 kind: Service
21 metadata:
22 name: myapp-svc
23 spec:
24 selector:
25 app: myapp
26 ports:
27 - protocol: TCP
28 port: 80 #服务端口
29 targetPort: 80 #pod/容器内端口
#在之前的ingress.yaml文件中添加www2.westos.org的域名
[root@server2 ingress]# vim ingress.yaml
1 apiVersion: networking.k8s.io/v1
2 kind: Ingress
3 metadata:
4 name: ingress-demo
5 spec:
6 ingressClassName: nginx
7 rules:
8 - host: www1.westos.org
9 http:
10 paths:
11 - path: / #直接访问根目录
12 pathType: Prefix
13 backend: #设置后端的svc
14 service:
15 name: myservice #后端的svc名称,必须匹配
16 port:
17 number: 80
18 - host: www2.westos.org
19 http:
20 paths:
21 - path: / #直接访问根目录
22 pathType: Prefix
23 backend: #设置后端的svc
24 service:
25 name: myapp-svc #后端的svc名称,必须匹配
26 port:
27 number: 80
测试:在外部主机上分别访问这两个域名,会被ingress调度到不同的svc上
(3)ingress examples
Introduction - NGINX Ingress Controllerhttps://kubernetes.github.io/ingress-nginx/examples/
(4)ingress加密
TLS termination - NGINX Ingress Controllerhttps://kubernetes.github.io/ingress-nginx/examples/tls-termination/ 创建证书并导入kubectl
#生成证书和密钥
[root@server2 ingress]# openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
Generating a 2048 bit RSA private key
..............................................................+++
..........+++
writing new private key to 'tls.key'
-----
#导入证书和密钥
[root@server2 ingress]# kubectl create secret tls tls-secret --key tls.key --cert tls.crt
secret/tls-secret created
#查看kubectl中的证书
[root@server2 ingress]# kubectl get secrets
NAME TYPE DATA AGE
default-token-tcwmq kubernetes.io/service-account-token 3 7d21h
tls-secret kubernetes.io/tls 2 11s
[root@server2 ingress]# vim ingress.yaml
1 apiVersion: networking.k8s.io/v1
2 kind: Ingress
3 metadata:
4 name: ingress-demo
5 spec:
6 tls: #添加加密策略
7 - hosts:
8 - www1.westos.org
9 secretName: tls-secret #指定加密的pod
10 ingressClassName: nginx
11 rules:
12 - host: www1.westos.org
13 http:
14 paths:
15 - path: / #直接访问根目录
16 pathType: Prefix
17 backend: #设置后端的svc
18 service:
19 name: myservice #后端的svc名称,必须匹配
20 port:
21 number: 80
22 - host: www2.westos.org
23 http:
24 paths:
25 - path: / #直接访问根目录
26 pathType: Prefix
27 backend: #设置后端的svc
28 service:
29 name: myapp-svc #后端的svc名称,必须匹配
30 port:
31 number: 80
测试:当外部主机访问80端口时,会自动重定向到ingress的443端口
(5)ingress认证
Basic Authentication - NGINX Ingress Controllerhttps://kubernetes.github.io/ingress-nginx/examples/auth/basic/生成认证文件并导入kubectl资源中
#安装生成认证密钥的工具httpd-tools
yum install -y httpd-tools
#创建认证用户
[root@server2 ingress]# htpasswd -c auth admin
New password: westos
Re-type new password: westos
Adding password for user admin
#将用户认证文件加载到kubectl资源中
[root@server2 ingress]# kubectl create secret generic basic-auth --from-file=auth
#查看用户认证pod资源是否就绪
[root@server2 ingress]# kubectl get secrets
NAME TYPE DATA AGE
basic-auth Opaque 1 20s
default-token-tcwmq kubernetes.io/service-account-token 3 7d21h
tls-secret kubernetes.io/tls 2 19m
在ingress.yaml中添加用户认证的选项
[root@server2 ingress]# vim ingress.yaml
1 apiVersion: networking.k8s.io/v1
2 kind: Ingress
3 metadata:
4 name: ingress-demo
5 annotations: #添加用户认证的选项
6 nginx.ingress.kubernetes.io/auth-type: basic
7 nginx.ingress.kubernetes.io/auth-secret: basic-auth
8 nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - admin'
9 spec:
10 tls:
11 - hosts:
12 - www1.westos.org
13 secretName: tls-secret
14 ingressClassName: nginx
15 rules:
16 - host: www1.westos.org
17 http:
18 paths:
19 - path: / #直接访问根目录
20 pathType: Prefix
21 backend: #设置后端的svc
22 service:
23 name: myservice #后端的svc名称,必须匹配
24 port:
25 number: 80
26 - host: www2.westos.org
27 http:
28 paths:
29 - path: / #直接访问根目录
30 pathType: Prefix
31 backend: #设置后端的svc
32 service:
33 name: myapp-svc #后端的svc名称,必须匹配
34 port:
35 number: 80
重新运行ingress.yaml文件后,可以看到认证信息。意味着访问这个域名需要认证。
测试:
(6)ingress重定向
Rewrite - NGINX Ingress Controllerhttps://kubernetes.github.io/ingress-nginx/examples/rewrite/
在ingress.yaml文件中添加重定向语句,格式如下:
[root@server2 ingress]# vim ingress.yaml
1 apiVersion: networking.k8s.io/v1
2 kind: Ingress
3 metadata:
4 name: ingress-demo
5 annotations:
6 nginx.ingress.kubernetes.io/app-root: /hostname.html #重定向
******
测试:设置好后,通过浏览器测试,输入“www1.westos.org”时会自动重定向到“www1.westos.org/hostname.html”
10、ingress的高级功能
annotations参数:
金丝雀发布(canary):
Annotations - NGINX Ingress Controllerhttps://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#canary金丝雀发布的简介:
kubernetes基于nginx-ingress进行蓝绿部署/金丝雀发布(canary)在关闭版本A后部署版本B. 此技术意味着服务的停机时间取决于应用程序的关闭和启动持续时间。 对用户的影响很大http://idcsec.com/2019/09/12/kubernetes%E5%9F%BA%E4%BA%8Enginx-ingress%E8%BF%9B%E8%A1%8C%E8%93%9D%E7%BB%BF%E9%83%A8%E7%BD%B2-%E9%87%91%E4%B8%9D%E9%9B%80%E5%8F%91%E5%B8%83canary/几年前的发布方式:
kubernetes滚动更新方式:
蓝绿部署:
canary:
A / B测试:
11、金丝雀(canary)发布实践
在之前实验的基础上,将两个svc的名称分别更改为“myapp-v1”和“myapp-v2”,用于模拟两套版本,查看版本迭代效果。(删掉之前的ingress,防止对本实验有影响)
“myapp-v1”版本如下:
[root@server2 ingress]# vim v1-ingress.yaml
1 apiVersion: networking.k8s.io/v1
2 kind: Ingress
3 metadata:
4 name: ingress-myapp
5 spec:
6 ingressClassName: nginx
7 rules:
8 - host: myapp.westos.org
9 http:
10 paths:
11 - path: /
12 pathType: Prefix
13 backend:
14 service:
15 name: myapp-v1
16 port:
17 number: 80
令其生效后,在外部主机访问,可以看到当前镜像版本为“mapp-v1”
如果现在需要更新到“myapp-v2”版本,用金丝雀的方式让v1的流量慢慢移动到v2上。
[root@server2 ingress]# vim v2-ingress.yaml
1 apiVersion: networking.k8s.io/v1
2 kind: Ingress
3 metadata:
4 name: ingress-myapp-canary
5 annotations:
6 nginx.ingress.kubernetes.io/canary: "true" #启用金丝雀方式
7 nginx.ingress.kubernetes.io/canary-weight: "10" #先转移10%的流量
8 spec:
9 ingressClassName: nginx
10 rules:
11 - host: myapp.westos.org
12 http:
13 paths:
14 - path: /
15 pathType: Prefix
16 backend:
17 service:
18 name: myapp-v2
19 port:
20 number: 80
在宿主机测试,大约是每访问10次就会有一次的被分配到v2上
接下来将流量比例调整为50,意味着每访问100次,就有50次被分配到v2上。在宿主机通过一个脚本实现,脚本内容如下:
[root@westos_student50 docker]# vim v1-v2.sh
1 #!/bin/bash
2
3 v1=0
4 v2=0
5
6 for (( i=0; i<100; i++))
7 do
8 response=`curl -s myapp.westos.org |grep -c v1`
9
10 v1=`expr $v1 + $response`
11 v2=`expr $v2 + 1 - $response`
12
13 done
14
15 echo "v1:$v1, v2:$v2"
12、calico网络插件
(1)calico网络插件官网
Install Calico networking and network policy for on-premises deploymentshttps://projectcalico.docs.tigera.io/getting-started/kubernetes/self-managed-onprem/onpremises
(2)calico简介:
(3)calico网络架构
(4)calico工作模式
(5)calico安装及部署
#下载calico.yaml文件
curl https://projectcalico.docs.tigera.io/manifests/calico.yaml -O calico.yaml
#更改calico.yaml中的镜像源为本地镜像仓库的名称
[root@server2 calico]# cat calico.yaml |grep image
image: calico/cni:v3.22.0
image: calico/cni:v3.22.0
image: calico/pod2daemon-flexvol:v3.22.0
image: calico/node:v3.22.0
image: calico/kube-controllers:v3.22.0
calico.yaml文件中涉及到的几个镜像已经打包好放在本地仓库中了。
#在server2中清除之前的flannel组件
[root@server2 ~]# kubectl delete -f kube-flannel.yml
#在每个节点中删除掉冗余的配置文件
[root@server2 net.d]# rm -f /etc/cni/net.d/10-flannel.conflist
#运行calico.yml文件,并查看各节点是否准备就绪
[root@server2 calico]# kubectl apply -f calico.yaml
[root@server2 calico]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-599bb85f6d-pkzzv 1/1 Running 0 80s
calico-node-7r29t 1/1 Running 0 80s
calico-node-fn49q 0/1 Running 0 80s
calico-node-qf6t2 0/1 Running 0 80s
为了不受之前实验的干扰,删除掉之前所有的pod
579 kubectl delete -f v1-ingress.yaml
580 kubectl delete -f v2-ingress.yaml
581 kubectl delete svc --all
582 kubectl delete deployments.apps deployment-myapp
583 kubectl delete deployments.apps deployment-nginx
然后重新新建一个项目。并且在集群内测试已经没有问题了。
要从集群外部访问还需要一个ingress,所以就启动一个之前的“v1-ingress.yaml”
测试:在外部主机上访问集群内部,已经可以正常访问了 。因此证明calico已经安装完成
(6)calico网络策略
NetworkPolicy策略模型:控制某个namespace下的pod的网络出入站规则
calico网络策略官方文档:
声明网络策略 | Kubernetes本文可以帮助你开始使用 Kubernetes 的 NetworkPolicy API 声明网络策略去管理 Pod 之间的通信说明: 本部分链接到提供 Kubernetes 所需功能的第三方项目。Kubernetes 项目作者不负责这些项目。此页面遵循CNCF 网站指南,按字母顺序列出项目。要将项目添加到此列表中,请在提交更改之前阅读内容指南。 准备开始 你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 建议在至少有两个节点的集群上运行本教程,且这些节点不作为控制平面主机。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建: Katacoda 玩转 Kubernetes 您的 Kubernetes 服务器版本必须不低于版本 v1.8. 要获知版本信息,请输入 kubectl version. 你首先需要有一个支持网络策略的 Kubernetes 集群。已经有许多支持 NetworkPolicy 的网络提供商,包括: Antrea Calico Cilium Kube-router Romana Weave 网络 创建一个nginx Deployment 并且通过服务将其暴露 为了查看 Kubernetes 网络策略是怎样工作的,可以从创建一个nginx Deployment 并且通过服务将其暴露开始kubectl create deployment nginx --image=nginx deployment.apps/nginx created 将此 Deployment 以名为 nginx 的 Service 暴露出来:https://kubernetes.io/zh/docs/tasks/administer-cluster/declare-network-policy/网络策略 | Kubernetespod is allowed to communicate with various network "entities" (we use the word "entity" here to avoid overloading the more common terms such as "endpoints" and "services", which have specific Kubernetes connotations) over the network. -- 如果你希望在 IP 地址或端口层面(OSI 第 3 层或第 4 层)控制网络流量, 则你可以考虑为集群中特定应用使用 Kubernetes 网络策略(NetworkPolicy)。 NetworkPolicy 是一种以应用为中心的结构,允许你设置如何允许 Pod 与网络上的各类网络“实体” (我们这里使用实体以避免过度使用诸如“端点”和“服务”这类常用术语, 这些术语在 Kubernetes 中有特定含义)通信。Pod 可以通信的 Pod 是通过如下三个标识符的组合来辩识的: 其他被允许的 Pods(例外:Pod 无法阻塞对自身的访问) 被允许的名字空间 IP 组块(例外:与 Pod 运行所在的节点的通信总是被允许的, 无论 Pod 或节点的 IP 地址) selector to specify what traffic is allowed to and from the Pod(s) that match the selector.
https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/
实验1——设置calico网络策略,内容如下:
[root@server2 calico]# vim policy.yaml
1 apiVersion: networking.k8s.io/v1
2 kind: NetworkPolicy
3 metadata:
4 name: access-nginx
5 spec:
6 podSelector:
7 matchLabels:
8 app: nginx #只针对nginx的标签作出限制
9 ingress: #入站的请求只有通过有此标签的pod才能访问
10 - from:
11 - podSelector:
12 matchLabels:
13 access: "true"
policy.yaml文件策略生效后,只针对标签为“app=nginx”的pod有效。
由于网络策略中设置为“入站的请求只有通过有此标签的pod才能访问”,而发出请求的pod标签不是“nginx”,因此在集群内无法访问该pod了
再通过其他镜像测试,可以看到因为新建的busyboxplus镜像的标签为“demo”,因此还是无法访问pod内部。
在另一个终端上连接server2,将demo的标签改为“access=true”。拥有此标签后,再次从busyboxplus中访问,可以访问到pod内部了。
#更改demo的标签
[root@server2 ~]# kubectl label pod demo access=true
pod/demo labeled
#查看demo的标签
[root@server2 ~]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
demo 1/1 Running 0 51s access=true,run=demo
实验2——设置calico网络策略,内容如下:
表示匹配pod标签为“access=true”的请求可以访问;或者从namespace上限制“test”的pod可以访问
[root@server2 calico]# vim policy.yaml
1 apiVersion: networking.k8s.io/v1
2 kind: NetworkPolicy
3 metadata:
4 name: access-nginx
5 spec:
6 podSelector:
7 matchLabels:
8 app: nginx
9 ingress:
10 - from:
11 - podSelector: #策略1
12 matchLabels:
13 access: "true"
14 - namespaceSelector: #策略2
15 matchLabels:
16 role: "test"
新建一个test的namespace,但是它的标签还是默认的
#创建一个名为test的namespace
[root@server2 calico]# kubectl create namespace test
重新运行之前的demo,这次运行的namespace在test上。在busyboxplus中测试,无法访问内部pod。
#为test的namespace为添加标签
[root@server2 calico]# kubectl label ns test role=test
namespace/test labeled
[root@server2 calico]# kubectl get ns --show-labels
test Active 5m30s kubernetes.io/metadata.name=test,role=test
再次测试后可以看到,允许正常访问pod了。
注意:写多个策略时,加不加“-”有很大区别,加上“-”表示或者,满足一个条件即可;不加“-”表示并且,所有条件必须同时满足。
九、kubectl命令指南
#导入本地镜像包
docker load -i base-debian10.tar (镜像名)
Master查看状态:
kubectl get cs
kubectl get node
kubectl get pod -n kube-system -o wide
#创建pod
[root@server2]# kubectl apply -f demo.yml
#删除pod(两种方式)
[root@server2]# kubectl delete -f demo.yml
[root@server2]# kubectl delete pod liveness-http
#查看pod的具体信息
kubectl get pod -n kube-system -o wide #显示kube-system域中的所有pod
kubectl describe pod nginx #显示名为nginx的pod信息,不加-n表示在默认namespace查看
kubectl logs nginx -n kube-system #显示nginx日志,-n:指定namespace为kube-system
kubectl logs nginx -c init-container #显示名为nginx的pod下的init-container容器的日志
#查看所有namespace
[root@server2 ~]# kubectl get ns
NAME STATUS AGE
default Active 3d4h
kube-node-lease Active 3d4h
kube-public Active 3d4h
kube-system Active 3d4h
#指定namespace
[root@server2 ~]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-7b56f6bc55-6httc 1/1 Running 1 (28m ago) 3d4h
coredns-7b56f6bc55-k5fnm 1/1 Running 1 (28m ago) 3d4h
#手动创建容器
kubectl run -it demo --image=busybox --restart=Never #-it,交互式
#查看pod的标签
[root@server2 init]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
liveness-http 0/1 Running 0 64m test=liveness
#进入pod内部,并通过bash操作
[root@server2 init]# kubectl exec -it liveness-http -- bash #liveness-http为pod名字
#显示pod标签
[root@server2 pod]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
replicaset-example-8lwkf 1/1 Running 0 3m50s app=nginx
replicaset-example-hdgc8 1/1 Running 0 3m50s app=nginx
replicaset-example-w4zpt 1/1 Running 0 3m50s app=nginx
#更改上述pod标签
[root@server2 pod]# kubectl label pod replicaset-example-8lwkf app=myapp --overwrite