k8s学习笔记

K8S学习

云计算课程学习笔记

公网ip与私网ip的区别

公网ip:任何人在任何地点都能访问到的ip

私网ip:内部服务器网卡真正用的ip,固定不变的,搭建的集群的每个私有ip都不变的。

服务器集群

服务器内部访问,通过私有ip访问。当然服务器之间通过公网ip访问也是可以的,但是如果是在同一个集群内,如果用私网ip,就不会走公网的流量,不会收费。而且网速比较快,不会有网络带宽的限制。

VPC:专有网络、私有网络

网段:这个网络(vpc)下,一定会连接很多的云服务器资源,以及每个服务器的ip地址都是vpc指定的网段范围。能够划分的可用的网段。

如192.168.0.0/16,表示成二进制后是一个八位数。利用子网计算功能:

掩码位的功能的是:

192.168.0.0转换成二进制是:

11000000.10101000.00000000.00000000/16,掩码位是指前16位不变,后面的随机变化。所以该网段是192.168.0.0~192.168.255.255=256*256=65536。可以有6万台左右机器。但是192.168.0.0是起始,192.168.255.255是广播地址,是不可用的。所以真正可用的ip数量一共是65536- 1- 1=65534

这个网段太大了。

所以可以在vpc继续规划子网。

交换机的意思是继续创建子网。

IPv4网段的意思是继续用交换机继续划分子网:

划分的依据是前面24位保持不变,那么这个网段有256个ip,一共有254个机器可用。

通过改变网段,又可以划分出来一个ip网段,也能容纳254个机器。

vpc之间是隔离的

途中两个vpc虽然使用了同一个ip网段,但是他们之间是隔离的,不会相互冲突。

比如两个小区都是192.168.0.0,网段是一样的,但是物理上隔离的。公网路由会丢掉保留的私网ip地址,所以这个ip是隔离的。在同一个vpc网络,网络是互通的。比如测试和生产的机器都是192.168.0.0这个网段,但是物理上隔离的,增加了安全性。

docker基本概念

解决问题:

应用构建的统一标准

Java、C++、Javascript

打成软件包。像window的exe一样,通过docker build命令=====>镜像

应用共享

旧的都是通过网络下载或者通过U盘下载,docker把所有的应用放到docker hub上下载,类似于安卓的应用市场。

应用的运行

旧:通过Java -jar 来运行,C++的通过编译。docker 通过docker run 统一运行。

容器化时代

虚拟化技术(重量级):通过给tomcat、数据库、redis安装一个虚拟机,即使一个发生内存泄漏而不会把内存使用完,能够保证程序的正常运行。缺点:镜像很大,启动速度很慢,移植与分享不方便(把虚拟机拷贝一份)。

容器化技术:将不同linux的操作系统的差异化函数库打包到镜像中。通过沙箱机制,保证容器安全,启动速度快。

资源隔离

cpu、memory资源隔离与限制

访问设备隔离与限制

资源仓库

docker hub

安装

bash 复制代码
### 配置yum源
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
## 安装docker sudo yum install -y docker-ce docker-ce-cli containerd.io
#以下是在安装k8s的时候使用
yum install -y docker-ce-20.10.7 docker-ce-cli-20.10.7  containerd.io-1.4.6
## 配置镜像加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://s90ld29q.mirror.aliyuncs.com"],
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
启动

systemctl enable docker --now

nginx的开机自动运行

docker run --name=mynginx -d --restart=always nginx

redis

安装redis

docker安装redis命令:

docker pull redis

安装时,考虑redis的数据和配置挂载到外部宿主机上。

配置:/data/redis/conf 数据:/data/redis/data

启动redis

docker run 命令如果没有指定自定义启动命令,容器是不会加载自定义的配置文件的。

容器内部使用自定义位置配置文件的启动命令:

"redis-server","/etc/redis/redis.conf"

docker run -p 6379:6379 --name myredis -v /usr/local/docker/redis.conf:/etc/redis/redis.conf -v /usr/local/docker/data:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes
docker run -d redis redis-server /usr/local/etc/redis/redis.conf

部署

  • 1、以前的方式

①springboot打包成可执行的jar包。

②拿到jar包后,上传到服务器,执行java -jar D:\A-Study\MyFirstDockerProject\target\java-demo-0.0.1-SNAPSHOT.jar

如下图:

存在问题:需要装Java环境,或者其他的Python环境

  • 2、通过docker部署(DockerFile)
    所有机器都安装docker ,任何应用都是镜像,所有机器都可以运行。
    创建Dockerfile文件

①FROM 基础运行环境

在Docker hub上查找基础版本openjdk,在Tags中搜索8-jdk,不要window版本的,window版本的比较大。查找Linux版本的。

docker pull openjdk:8-jdk-slim

Dockerfile 复制代码
FROM openjdk:8-jdk-slim

② LABEL 写作者的标签

Dockerfile 复制代码
FROM openjdk:8-jdk-slim
LABEL maintainer=leifengyang

③COPY 把目标文件拷贝到镜像中

Dockerfile 复制代码
FROM openjdk:8-jdk-slim
LABEL maintainer=leifengyang
COPY target/*.jar /java-demo.jar

④ENTRYPOINT 镜像的启动命令或者写CMD

Dockerfile 复制代码
FROM openjdk:8-jdk-slim
LABEL maintainer=xiaguangpei
COPY target/*.jar /java-demo.jar
ENTRYPOINT ["java","-jar","java-demo.jar"]

按照如下,在服务器打放置文件:

⑤采用docker命令制作镜像

docker build -t java-demo:v1.0 .

-t的意思是标签名。

-f 是使用哪个文件指导创建镜像,,如果名字是Dockerfile就可以不写-f

.表示在哪个目录下构建镜像。

查看构建成功的镜像:

通过 docker logs -f --details containername查看docker详细日志

-f 是跟踪的意思,有日志就会打印出。

⑥将镜像推送到docker hub

给老的镜像打个标签

docker tag java-demo:v1.0 xiaguangpei/java-demo:v1.0

推送到docker hub仓库

docker push xiaguangpei/java-demo:v1.0

k8s

k8s:的集群架构:N Master Node + N Worker Node(N主节点+N工作节点) N >=1

k8s:容器编排技术。

组件架构

Control Plane控制面板(主节点)(硅谷总部):控制工厂生产。

Controller Mannager:决策者。维持副本期望数目。

etcd:资料,类似Redis的KeyValue。键值对数据库,存储K8S集群所有重要信息(持久化)。

Api Server:秘书部:与etcd与Nodes进行交互。所有服务访问统一入口

Scheduler:调度者。负责接受任务,选择合适的节点进行分配任务,需要清楚网盘,内存等资源大小。

Kubelet:每个厂的厂长。由ApiServer负责通知生产。监控每个厂的运行情况。本厂生产线的启动和停止。如果本厂实在坏了 ,就通知Api Server ,然后Api Server 通知决策者,决策者就更换其他厂生产,然后秘书处在etcd更新厂的运行和生产情况。秘书处通知调度者,就计算一下,把生产情况分析资料,并决策情况存储到etcd。然后api-server就把决策通知到每个厂的厂长。然后由厂长开始执行每个项目。直接跟容器引擎交互实现容器的生命周期管理。

K-proxy:看门大爷。本厂的传达室。相当于网关,负责对外的访问和路由、负载。负责写入规则至IPVS或者IPtable,实现服务的映射访问。

CoreDNS:可以为集群中的SVC创建一个域名IP的对应对应关系解析

DashBoard:给K8S集群提供一个B/S的访问结构体系

Ingress Controller:官方只能实现四层代理,而它可以实现七层代理

Fedetation:可以提供一个跨集群中心多K8S统一管理功能

Prometheus:提供一个K8S的集群监控能里

ELK:提供K8S集群日志统一分析 介入平台。

由程序员控制Kubernates控制中心:kubctl。

集群部署

kubectl和kubeadm、kubelet

kubelet:①k8s进行交互,获取pod相关的数据,监控当前的Pod变化的事件。②kubelet操作当前宿主机的资源信息,并启动Pod

kubectl:由程序员通过这两个命令给集群发号命令,但实际上只需要给master节点安装即可。

kubeadm:由程序员快速搭建集群。

docker::必须安装。

初始化

kubeadm:初始化一个主节点,k8s会把当前节点视为主节点。主节点的所有内容由kubelet安装,scheduler、kube-proxy、api-server、etcd、controller-manager。然后通过kubeadmin join 加入master节点,就可以了,kubelet就会给子节点安装kube-proxy。

集群部署

ip a:查看ip地址。输出如下:

root@iZm5e5hhykoa3gmhgf0u6sZ \~\]# ip a 1: lo: \ mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: eth0: \ mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:16:3e:04:33:b0 brd ff:ff:ff:ff:ff:ff inet 172.26.163.27/20 brd 172.26.175.255 scope global dynamic noprefixroute eth0 valid_lft 314925183sec preferred_lft 314925183sec 集群之间,通过内网通讯,通过eth0网卡通讯,通过私网ip通讯。ping心跳检测其他服务器。

kubectl和kubelet、kubeadm

装好kubectl和kubelet,用kubeadm工具整一个主节点,再通过kubeadm安装加入一些子节点。

kubelet:①k8s进行交互,获取pod相关的数据,监控当前的Pod变化的事件。②kubelet操作当前宿主机的资源信息,并启动Pod

kubectl:由程序员通过这两个命令给集群发号命令,但实际上只需要给master节点安装即可。

kubeadm:由程序员快速搭建集群。

docker::必须安装。即提供容器化运行环境。

初始化

kubeadm:初始化一个主节点,k8s会把当前节点视为主节点。主节点的所有内容由kubelet安装,scheduler、kube-proxy、api-server、etcd、controller-manager。然后通过kubeadmin join 加入master节点,就可以了,kubelet就会给子节点安装kube-proxy。

设置主机名与清空交换分区

1、hostnamectl 设置主机名

2、free -m清空交换分区

bash 复制代码
#各个机器设置自己的域名
hostnamectl set-hostname k8s-node1
# 将 SELinux 设置为 permissive 模式(相当于将其禁用)
#控制当前窗口规则
sudo setenforce 0 
# 通过修改配置达到永久禁用
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config 

#关闭swap
swapoff -a  
sed -ri 's/.*swap.*/#&/' /etc/fstab
# 将ipv6的流量桥接至ipv4网卡上,便以统计。k8s官方要求这么做。
#允许 iptables 检查桥接流量
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
# 察看所有的linux的内核配置。
sudo sysctl --system
配置k8s的源地址及安装kubeadm、kubectl、kubelet
bash 复制代码
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
   http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF
sudo yum install -y kubelet-1.20.9 kubeadm-1.20.9 kubectl-1.20.9 --disableexcludes=kubernetes

sudo systemctl enable --now kubelet
使用kubeadm引导启动集群

kubeadm:kubelet会在每一台机器上安装kube-proxy,kubelet会下载镜像,启动容器。所以除了kubelet,剩下的都是以容器化的方式运行。但是下载镜像可能会卡住,所以提前配置了镜像,防止下载阶段被卡住。

下载各个机器需要的镜像

一般情况下,主节点需要所有下载项镜像。子节点只需要kube-proxy。但是保险期间,所有的节点都配置这些镜像

bash 复制代码
sudo tee ./images.sh <<-'EOF'
#!/bin/bash
images=(
kube-apiserver:v1.20.9
kube-proxy:v1.20.9
kube-controller-manager:v1.20.9
kube-scheduler:v1.20.9
coredns:1.7.0
etcd:3.4.13-0
pause:3.2
)
for imageName in ${images[@]} ; do
docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/$imageName
done
EOF
chmod +x ./images.sh && ./images.sh
初始化主节点
bash 复制代码
# 设置域名映射 所有节点都执行这句话,这样所有节点都知道主节点在哪里了。下面只有主节点才需要执行 172.26.163.34替换为主节点的ip
echo "172.26.163.34  cluster-endpoint" >> /etc/hosts
#主节点初始化 172.26.163.34替换为主节点的ip
# 主节点初始化时service-cidr和pod-network-cidr不能重叠且不能和机器的ip重叠
kubeadm init \
--apiserver-advertise-address=172.26.163.34 \
--control-plane-endpoint=cluster-endpoint \
--image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
--kubernetes-version v1.20.9 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=192.168.0.0/16
#
## 如果初始化时修改了pod-network-cidr=192.168.0.0/16
## 需要在images.sh中执行
cat calico.yaml |grep 192.168.0.0/16
## 把以上ip改成自定义的ip。
##初始化失败时,需要重新初始化:
kubeadm reset

从初始化完成之后返回的信息,表示初始化成功!要保留kubeadm join cluster-endpoint:6443。。。。。

bash 复制代码
Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:

  kubeadm join cluster-endpoint:6443 --token vf9b2z.uaew25u339kryzfy \
    --discovery-token-ca-cert-hash sha256:803831192e259ad8287751b244afb0e8c442b2e4223472b735eebd83515d81d0 \
    --control-plane 

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join cluster-endpoint:6443 --token vf9b2z.uaew25u339kryzfy \
    --discovery-token-ca-cert-hash sha256:803831192e259ad8287751b244afb0e8c442b2e4223472b735eebd83515d81d0 
bash 复制代码
# 把以下命令在控制台上执行:
# 把核心配置复制到了这个目录下,给了一些权限
  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config
根据提示安装网络组件
bash 复制代码
### 下载配置文件
curl https://docs.projectcalico.org/v3.18/manifests/calico.yaml -O
### 给k8s集群创建资源:
kubectl apply -f calico.yaml
##查看集群部署了哪些应用。
## docker ps === kubectl get pods -A
kubectl get pods -A
## 只有在主节点kubectl get pods -A才能知道运行了多少个pods
## 运行中的应用:docker中叫容器,k8s中叫pods
初始化从节点
bash 复制代码
# 每个节点都执行,都能通过域名找到主节点.172.26.163.28替换为对应的主机IP.
echo "172.26.163.28  cluster-endpoint" >> /etc/hosts

初始化从节点时报错问题

bash 复制代码
[root@k8s-node2 ~]# kubeadm join cluster-endpoint:6443 --token 73nftg.oig0ajmy3e0tgqou     --discovery-token-ca-cert-hash sha256:e49ef870805b18ba8df13a731e8428d1019d01a550b5d017a72b7bf1669ec76f 
[preflight] Running pre-flight checks
        [WARNING FileExisting-tc]: tc not found in system path
        [WARNING SystemVerification]: this Docker version is not on the list of validated versions: 20.10.7. Latest validated version: 19.03
        [WARNING Hostname]: hostname "k8s-node2" could not be reached
        [WARNING Hostname]: hostname "k8s-node2": lookup k8s-node2 on 100.100.2.136:53: no such host
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
[kubelet-check] Initial timeout of 40s passed.
error execution phase kubelet-start: error uploading crisocket: timed out waiting for the condition
To see the stack trace of this error execute with --v=5 or higher

采用以下命令修复

这项配置也需要:

bash 复制代码
# Docker是用yum安装的,docker的cgroup驱动程序默认设置为system。默认情况下Kubernetes cgroup为systemd,我们需要更改Docker cgroup驱动,
vim /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"]
}
# 重启docker
systemctl restart docker
bash 复制代码
rm -f /etc/kubernetes/pki/ca.crt
rm -f /etc/kubernetes/kubelet.conf
swapoff -a
kubeadm reset
systemctl daemon-reload
systemctl restart kubelet
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
kubeadm join cluster-endpoint:6443 --token 73nftg.oig0ajmy3e0tgqou     --discovery-token-ca-cert-hash sha256:e49ef870805b18ba8df13a731e8428d1019d01a550b5d017a72b7bf1669ec76f
k8s查看显示一个或者多个资源
bash 复制代码
[root@k8s-master ~]# kubectl get pod -A
# 名称,就绪数量、状态(数量)、重启次数(k8s的自愈能力)
NAMESPACE     NAME                                      READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-dd89d97f8-vd62f   1/1     Running   0          12m
kube-system   calico-node-p54vb                         0/1     Running   0          12m
kube-system   coredns-5897cd56c4-g4p6s                  1/1     Running   0          31m
kube-system   coredns-5897cd56c4-m9ttx                  1/1     Running   0          31m
kube-system   etcd-k8s-master                           1/1     Running   0          31m
kube-system   kube-apiserver-k8s-master                 1/1     Running   0          31m
kube-system   kube-controller-manager-k8s-master        1/1     Running   0          31m
kube-system   kube-proxy-5fttf                          1/1     Running   0          31m
kube-system   kube-scheduler-k8s-master                 1/1     Running   0          31m

k8s的自我修复能力测试

假设服务器宕机,然后重启k8s的整个集群,测试k8s的整个集群能不能重新启动起来,一切都准备好,不用人工干预。

模拟重启服务器

bash 复制代码
reboot

启动后:

bash 复制代码
[root@k8s-master ~]# kubectl get nodes
NAME         STATUS   ROLES                  AGE   VERSION
k8s-master   Ready    control-plane,master   37m   v1.20.9
k8s-node1    Ready    <none>                 24m   v1.20.9
k8s-node2    Ready    <none>                 24m   v1.20.9
[root@k8s-master ~]# kubectl get pod -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-577f77cb5c-6mzw4   1/1     Running   1          32m
kube-system   calico-node-9lz2q                          0/1     Running   1          25m
kube-system   calico-node-hnhrt                          1/1     Running   1          32m
kube-system   calico-node-pz8d9                          1/1     Running   1          25m
kube-system   coredns-5897cd56c4-4nrvh                   1/1     Running   1          37m
kube-system   coredns-5897cd56c4-flc2m                   1/1     Running   1          37m
kube-system   etcd-k8s-master                            1/1     Running   2          37m
kube-system   kube-apiserver-k8s-master                  1/1     Running   2          37m
kube-system   kube-controller-manager-k8s-master         0/1     Running   2          37m
kube-system   kube-proxy-fb99g                           1/1     Running   1          25m
kube-system   kube-proxy-h5dbx                           1/1     Running   1          37m
kube-system   kube-proxy-sh74f                           1/1     Running   1          25m
kube-system   kube-scheduler-k8s-master                  0/1     Running   2          37m
[root@k8s-master ~]# kubectl get pod -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-577f77cb5c-6mzw4   1/1     Running   1          35m
kube-system   calico-node-9lz2q                          1/1     Running   1          27m
kube-system   calico-node-hnhrt                          1/1     Running   1          35m
kube-system   calico-node-pz8d9                          1/1     Running   1          28m
kube-system   coredns-5897cd56c4-4nrvh                   1/1     Running   1          40m
kube-system   coredns-5897cd56c4-flc2m                   1/1     Running   1          40m
kube-system   etcd-k8s-master                            1/1     Running   2          40m
kube-system   kube-apiserver-k8s-master                  1/1     Running   2          40m
kube-system   kube-controller-manager-k8s-master         1/1     Running   2          40m
kube-system   kube-proxy-fb99g                           1/1     Running   1          28m
kube-system   kube-proxy-h5dbx                           1/1     Running   1          40m
kube-system   kube-proxy-sh74f                           1/1     Running   1          27m
kube-system   kube-scheduler-k8s-master                  1/1     Running   2          40m

重新获取令牌指令

bash 复制代码
kubeadm token create --print-join-command

部署dashboard

bash 复制代码
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml
## 把k8s访问的端口号,暴漏到机器上。类似docker的-p 端口暴露
## 1、运行下面这个命令,输入 /type:搜索,将type: ClusterIP 改为 type: NodePort。然后保存
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
kubectl get svc -A |grep kubernetes-dashboard
bash 复制代码
  ports:
  - nodePort: 30955
    port: 443
    protocol: TCP
    targetPort: 8443
  selector:
    k8s-app: kubernetes-dashboard
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}
bash 复制代码
[root@k8s-master ~]# kubectl get svc -A |grep kubernetes-dashboard
## 30955这个端口就是未来访问k8s控制台的。
## 访问: https://集群任意IP:端口      https://47.104.148.65:30955/
kubernetes-dashboard   dashboard-metrics-scraper   ClusterIP   10.96.113.14   <none>        8000/TCP                 112m
kubernetes-dashboard   kubernetes-dashboard        NodePort    10.96.58.179   <none>        443:30955/TCP            112m

创建k8s用户:

bash 复制代码
## 创建文件 输入下面的文件内容
vi dash.yaml
## 应用
kubectl apply -f dash.yaml
yaml 复制代码
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard
bash 复制代码
[root@k8s-master ~]# kubectl apply -f dash-usr.yaml
serviceaccount/admin-user created
clusterrolebinding.rbac.authorization.k8s.io/admin-user created

admin-user创建了,但是不是通过用户密码登录的,而是通过令牌登录的,通过下面的命令获取令牌:

bash 复制代码
kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"
bash 复制代码
[root@k8s-master ~]# kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"
eyJhbGciOiJSUzI1NiIsImtpZCI6ImIxSVg1TU9Ub3JXVjViNzRPNmdUeVhiQWlIZWpiOUdTVXFKaVVNcE9oUkEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLTQ5Nnd3Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI2OTQ4NGNlYi1mNGU0LTQ4MzAtYTJiMS1mNzEwZGY2ZTE5ZTgiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.K_dh8eO3SrCr6-s_xwr-xhlS7asZO3hW4wah16YMpJrPg8IOaFQYiiRMCD1CC8P7HD8cx-XXsRN2oNSjPudpTArZWP85u4qle3mHQOmbVuLdkEzVARRXsoKkl6T4Cfu-vGyOwmBjT5PhY6MzMKMS9ymhFmlBZ9ih7qi2QSg2C0CNRrHdh0xgevGYq8oZ-iGZSl84wLs74djynNaMQCqp782Ga9-sQ4YmGN20cIPbsZe0BiXP0IpHIqQ2y-4KR6jXxD48tjrcnPw8D6Bex2BLtOjWHRoNjx9w1BrwcOioWTmSBk0V5MoUzz_HfJ5pyWOo1yXAHLhxfQhFv8Ch5kf2jg

Kubernetes核心实战

1、资源创建方式

  • 命令行
  • YAML

2、Namespace

隔离资源,不隔离网络

  • kubectl create ns hello
  • kubectl delete ns hello
bash 复制代码
# 获取所有的命名空间
kubectl get ns
bash 复制代码
如果不加-A,只打印默认default命名空间下的
kubectl get pod -A
## -n kube-system 指定命名空间
kubectl get pod -n kube-system
## 删除命名空间
kubectl delete ns mykubectl
## 创建命名空间
kubectl create ns hello
通过yaml 创建命名空间
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: myapp
  name: myapp
spec:
  containers:
  - image: nginx
    name: nginx
  - image: tomcat:8.5.68
    name: tomcat
bash 复制代码
## 创建命名空间
kubectl  apply -f hello.yaml
## 删除命名空间
kubectl delete -f hello.yaml

3、Pod

概念:pod是一组共享命名空间、卷、IP、PORT的运行中的一组容器,Pod是kubernetes中应用的最小单位。一组容器被k8s封装成了Pod,便于管理.。每个pod中有一个pause容器负责网络代理和挂载卷。k8s认为单个容器太小,不能视为一个单位,就将一组容器作为一个单位进行管理。一组容器负责一个事情。

bash 复制代码
## 运行一个nginx,用nginx镜像,名字是mynginx
kubectl run mynginx --image=nginx
bash 复制代码
[root@k8s-master ~]# kubectl run mynginx --image=nginx
pod/mynginx created
[root@k8s-master ~]# kubectl get pod 
NAME      READY   STATUS              RESTARTS   AGE
mynginx   0/1     ContainerCreating   0          23s

ContainerCreating :表示容器正在创建中,需要下载并启动

bash 复制代码
## k8s通过事件的方式描述容器
kubectl describe pod mynginx
bash 复制代码
## 删除容器,默认的不需要加命名空间
[root@k8s-master ~]# kubectl delete pod mynginx
pod "mynginx" deleted
网络通讯

同一个pod之间共享网络命名空间,共享同一个linux协议栈

pod之间:①pod1与pod2不在同一台主机,pod的地址是与docker0在同一个网段的,但docker0网段与宿主机网卡是两个完全不同的IP网段,并且不同的node之间通讯只能通过宿主机的物理网卡进行,将pod的ip地址和node的IP关联起来,通过这个关联可以互相访问。

②pod1与pod2在同一台机器,由docker0网桥直接转发请求至pod2,不需要Flannel.

pod与Service:①基于性能的考虑,全部为iptable、lvs维护和转发。

②pod到外网:pod向外网发送请求,查找路由表,转发数据包到宿主机的网卡,苏书记网卡完成路由选择后,iptables执行masquerade,把源ip更改为宿主机网卡的ip,然后向外网发送请求。

1、podA(这个ip地址CNI在Pod启动时分配的ip5)通过resolv.conf配置文件获取dns的ip地址ip1

2、向dns的ip1地址咨询实际服务B集群的虚拟服务地址ip2,根据集群B的服务地址向本机kube-proxy询问,

3、kubeproxy缓存或根据service的标签api-server向etcd获取了所有集群B的服务器ip列表,并根据

负载均衡选择一个健康节点ip3(这个ip地址CNI在Pod启动时分配的)

5、kubeproxy拿到这个podB的ip3(这个ip地址CNI在Pod启动时分配的ip3),然后根据访问的类型

5.0如果ip3是外网ip时,再把发送方ip5转换为主机网卡ip4(SNAT)。然后主机网卡将服务发送,然后返回后内核再将发送方ip4替换为ip5

将返回内容再返回给发送方的ip5。

5.1如果ip3是本pod的,就直接localhost访问.

5.2如果ip3是本node的(可以是物理机、虚拟机、云主机),就在本机器上做转发,通过内核/网桥直接转发,不经过物理网卡。

5.3如果ip3是其他node的,通过主机网卡ip4转发(一般保留源IP)。

通过yaml创建pod
bash 复制代码
[root@k8s-master ~]# vi mynginx.yaml
[root@k8s-master ~]# kubectl apply -f mynginx.yaml
pod/mynginx created
[root@k8s-master ~]# kubectl delete -f mynginx.yaml 
pod "mynginx" deleted
bash 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: mynginx
  name: mynginx
#  namespace: default
spec:
  containers:
  - image: nginx
    name: mynginx
dashboard 创建pod方式

没有指定命名空间时,无法创建pod

  • 有两种解决方案
    • 一种是通过指定命名空间
    • 文件中指定命名空间
日志
bash 复制代码
# 阻塞式查看日志
kubectl logs -f pod名称
bash 复制代码
# 打印pod的完善信息,查看访问的ip
kubectl get pod -owide

每个pod,k8s都会分配一个ip。采用ip+容器端口号就能访问到

进入容器内部
bash 复制代码
kubectl exec -it mynginx -- /bin/bash
root@mynginx:/# ls -l
total 80
drwxr-xr-x   2 root root 4096 Dec 20  2021 bin
drwxr-xr-x   2 root root 4096 Dec 11  2021 boot
drwxr-xr-x   5 root root  360 Sep 13 13:23 dev
drwxr-xr-x   1 root root 4096 Dec 29  2021 docker-entrypoint.d
-rwxrwxr-x   1 root root 1202 Dec 29  2021 docker-entrypoint.sh
drwxr-xr-x   1 root root 4096 Sep 13 13:23 etc
drwxr-xr-x   2 root root 4096 Dec 11  2021 home
drwxr-xr-x   1 root root 4096 Dec 20  2021 lib
drwxr-xr-x   2 root root 4096 Dec 20  2021 lib64
drwxr-xr-x   2 root root 4096 Dec 20  2021 media
drwxr-xr-x   2 root root 4096 Dec 20  2021 mnt
drwxr-xr-x   2 root root 4096 Dec 20  2021 opt
dr-xr-xr-x 144 root root    0 Sep 13 13:23 proc
drwx------   2 root root 4096 Dec 20  2021 root
drwxr-xr-x   1 root root 4096 Sep 13 13:23 run
drwxr-xr-x   2 root root 4096 Dec 20  2021 sbin
drwxr-xr-x   2 root root 4096 Dec 20  2021 srv
dr-xr-xr-x  13 root root    0 Sep 13 13:33 sys
drwxrwxrwt   1 root root 4096 Dec 29  2021 tmp
drwxr-xr-x   1 root root 4096 Dec 20  2021 usr
drwxr-xr-x   1 root root 4096 Dec 20  2021 var
思考题

为什么给pod分配了一个ip是192.168.36.77

答:主节点初始化引导master节点的时候 --pod-network-cidr=192.168.0.0/16,pod的网络的范围域,k8s给每一个pod分配网络,应该在哪个范围里分配。

创建多个容器

myapp中在同一个网络空间中,共享网络和存储。

bash 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: myapp
  name: myapp
spec:
  containers:
  - image: nginx
    name: nginx
  - image: tomcat:8.5.68
    name: tomcat
bash 复制代码
curl 192.168.169.130:8080

不能在一个pod中有两个nginx应用。因为一个pod中容器在一个网络空间中,可以认为一个pod代表一个Linux小虚拟机

4、Deployment

bash 复制代码
#### 同时删除两个pod
[root@k8s-master ~]# kubectl delete pod myapp mynginx -n default
pod "myapp" deleted
pod "mynginx" deleted

创建一个部署,而不是一个单纯的pod,那可以告诉k8s的副本数量,k8s就通过Deployment帮我控制副本的数量。

bash 复制代码
# 比较下面两个命令有何不同效果?
[root@k8s-master ~]# kubectl run mynginx --image=nginx
pod/mynginx created
[root@k8s-master ~]# kubectl create deployment mytomcat --image=tomcat:8.5.68
deployment.apps/mytomcat created
[root@k8s-master ~]# kubectl delete pod mytomcat-6f5f895f4f-bzxjc
pod "mytomcat-6f5f895f4f-bzxjc" deleted
# 自愈能力。即使通过delete命令把容器删除了,k8s也会给我们重新创建一个容器。
删除一个部署
bash 复制代码
[root@k8s-master ~]# kubectl get deploy
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
mytomcat   1/1     1            1           4m59s
[root@k8s-master ~]# kubectl delete deploy mytomcat
deployment.apps "mytomcat" deleted
[root@k8s-master ~]# kubectl get deploy
No resources found in default namespace.
副本能力:创建有三个副本的应用
bash 复制代码
[root@k8s-master ~]# kubectl create deploy my-dep --image=nginx --replicas=3
deployment.apps/my-dep created
[root@k8s-master ~]# kubectl get deploy
NAME     READY   UP-TO-DATE   AVAILABLE   AGE
my-dep   0/3     3            0           10s
分散部署:鸡蛋不放在一个篮子里
bash 复制代码
[root@k8s-master ~]# kubectl get pod -owide
NAME                        READY   STATUS    RESTARTS   AGE     IP                NODE        NOMINATED NODE   READINESS GATES
my-dep-01-6456cdfc7-bthwp   1/1     Running   0          56s     192.168.36.80     k8s-node1   <none>           <none>
my-dep-01-6456cdfc7-g7m8g   1/1     Running   0          56s     192.168.169.137   k8s-node2   <none>           <none>
my-dep-01-6456cdfc7-v4xmg   1/1     Running   0          56s     192.168.36.79     k8s-node1   <none>           <none>
my-dep-01-6456cdfc7-wmfr4   1/1     Running   0          56s     192.168.169.139   k8s-node2   <none>           <none>
my-dep-01-6456cdfc7-xj5z5   1/1     Running   0          56s     192.168.169.138   k8s-node2   <none>           <none>
my-dep-5b7868d854-9kmm9     1/1     Running   0          4m30s   192.168.36.78     k8s-node1   <none>           <none>
my-dep-5b7868d854-kf97p     1/1     Running   0          4m30s   192.168.169.135   k8s-node2   <none>           <none>
my-dep-5b7868d854-qf2nz     1/1     Running   0          4m30s   192.168.169.136   k8s-node2   <none>           <none>
mynginx                     1/1     Running   0          13m     192.168.169.132   k8s-node2   <none>           <none>

通过配置文件的方式创建具有副本的deployment

bash 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: my-dep
  name: my-dep
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-dep
  template:
    metadata:
      labels:
        app: my-dep
    spec:
      containers:
      - image: nginx
        name: nginx
扩缩容:动态扩缩容
bash 复制代码
[root@k8s-master ~]# kubectl get pod
NAME                      READY   STATUS    RESTARTS   AGE
my-dep-5b7868d854-9kmm9   1/1     Running   0          12m
my-dep-5b7868d854-kf97p   1/1     Running   0          12m
my-dep-5b7868d854-qf2nz   1/1     Running   0          12m
mynginx                   1/1     Running   0          21m
[root@k8s-master ~]# kubectl scale --replicas=5 deploy/my-dep
deployment.apps/my-dep scaled
[root@k8s-master ~]# kubectl get pod
NAME                      READY   STATUS              RESTARTS   AGE
my-dep-5b7868d854-2dsfg   0/1     ContainerCreating   0          15s
my-dep-5b7868d854-4blfx   0/1     ContainerCreating   0          15s
my-dep-5b7868d854-9kmm9   1/1     Running             0          13m
my-dep-5b7868d854-kf97p   1/1     Running             0          13m
my-dep-5b7868d854-qf2nz   1/1     Running             0          13m
mynginx                   1/1     Running             0          21m
修改 replicas
bash 复制代码
kubectl edit deployment my-dep
自愈能力

如果某个容器故障或者主机宕机,当达到心跳检测阈值时,即k8s达到5分钟没有检测到心跳就会触发自愈机制,在另外一台主机上重新部署一定数量的容器。

滚动更新

修改deployee中my-dep的nginx中的版本号,--record是记录一下。

bash 复制代码
kubectl get deploy my-dep -oyaml
[root@k8s-master ~]# kubectl set image deploy/my-dep  nginx=nginx:1.16.1 --record
    

不停机更新:假设旧的Deployment1运行时,重新部署新的Deployment2。他待Deployment2中的pod启动并运行稳定时,逐步用Deployment2中的pod替换Deployment1中的pod。实现滚动更新。

bash 复制代码
[root@k8s-master ~]# kubectl get pod -owide
NAME                      READY   STATUS    RESTARTS   AGE   IP              NODE        NOMINATED NODE   READINESS GATES
my-dep-5b7868d854-4blfx   1/1     Running   1          21h   192.168.36.90   k8s-node1   <none>           <none>
my-dep-5b7868d854-4phcv   1/1     Running   1          21h   192.168.36.86   k8s-node1   <none>           <none>
my-dep-5b7868d854-9kmm9   1/1     Running   1          21h   192.168.36.89   k8s-node1   <none>           <none>
[root@k8s-master ~]# kubectl get deploy my-dep
NAME     READY   UP-TO-DATE   AVAILABLE   AGE
my-dep   3/3     3            3           21h
[root@k8s-master ~]# kubectl get deploy my-dep -oyaml
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  creationTimestamp: "2022-09-13T14:44:59Z"
  generation: 3
  labels:
    app: my-dep
  managedFields:
  - apiVersion: apps/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:labels:
          .: {}
          f:app: {}
      f:spec:
        f:progressDeadlineSeconds: {}
        f:replicas: {}
        f:revisionHistoryLimit: {}
        f:selector: {}
        f:strategy:
          f:rollingUpdate:
            .: {}
            f:maxSurge: {}
            f:maxUnavailable: {}
          f:type: {}
        f:template:
          f:metadata:
            f:labels:
              .: {}
              f:app: {}
          f:spec:
            f:containers:
              k:{"name":"nginx"}:
                .: {}
                f:image: {}
                f:imagePullPolicy: {}
                f:name: {}
                f:resources: {}
                f:terminationMessagePath: {}
                f:terminationMessagePolicy: {}
            f:dnsPolicy: {}
            f:restartPolicy: {}
            f:schedulerName: {}
            f:securityContext: {}
            f:terminationGracePeriodSeconds: {}
    manager: kubectl-create
    operation: Update
    time: "2022-09-13T14:44:59Z"
  - apiVersion: apps/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .: {}
          f:deployment.kubernetes.io/revision: {}
      f:status:
        f:availableReplicas: {}
        f:conditions:
          .: {}
          k:{"type":"Available"}:
            .: {}
            f:lastTransitionTime: {}
            f:lastUpdateTime: {}
            f:message: {}
            f:reason: {}
            f:status: {}
            f:type: {}
          k:{"type":"Progressing"}:
            .: {}
            f:lastTransitionTime: {}
            f:lastUpdateTime: {}
            f:message: {}
            f:reason: {}
            f:status: {}
            f:type: {}
        f:observedGeneration: {}
        f:readyReplicas: {}
        f:replicas: {}
        f:updatedReplicas: {}
    manager: kube-controller-manager
    operation: Update
    time: "2022-09-14T12:06:13Z"
  name: my-dep
  namespace: default
  resourceVersion: "46443"
  uid: e1b2d136-e2c8-430a-a9d2-a5bc0b4365ec
spec:
  progressDeadlineSeconds: 600
  replicas: 3
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: my-dep
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: my-dep
    spec:
      containers:
      - image: nginx
        imagePullPolicy: Always
        name: nginx
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 3
  conditions:
  - lastTransitionTime: "2022-09-13T14:44:59Z"
    lastUpdateTime: "2022-09-13T14:45:16Z"
    message: ReplicaSet "my-dep-5b7868d854" has successfully progressed.
    reason: NewReplicaSetAvailable
    status: "True"
    type: Progressing
  - lastTransitionTime: "2022-09-14T12:05:58Z"
    lastUpdateTime: "2022-09-14T12:05:58Z"
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  observedGeneration: 3
  readyReplicas: 3
  replicas: 3
  updatedReplicas: 3
pod滚动更新
bash 复制代码
[root@k8s-master ~]# kubectl get pod -w
NAME                      READY   STATUS    RESTARTS   AGE
my-dep-5b7868d854-4blfx   1/1     Running   1          22h
my-dep-5b7868d854-4phcv   1/1     Running   1          21h
my-dep-5b7868d854-9kmm9   1/1     Running   1          22h
[root@k8s-master ~]# kubectl set image deploy/my-dep  nginx=nginx:1.16.1 --record
deployment.apps/my-dep image updated
[root@k8s-master ~]# kubectl get pod -w
NAME                      READY   STATUS    RESTARTS   AGE
my-dep-5b7868d854-4blfx   1/1     Running   1          22h
my-dep-5b7868d854-4phcv   1/1     Running   1          22h
my-dep-5b7868d854-9kmm9   1/1     Running   1          22h
my-dep-6b48cbf4f9-pqv85   0/1     Pending   0          0s
my-dep-6b48cbf4f9-pqv85   0/1     Pending   0          0s
my-dep-6b48cbf4f9-pqv85   0/1     ContainerCreating   0          0s
my-dep-6b48cbf4f9-pqv85   0/1     ContainerCreating   0          0s
my-dep-6b48cbf4f9-pqv85   1/1     Running             0          24s
my-dep-5b7868d854-4blfx   1/1     Terminating         1          22h
my-dep-6b48cbf4f9-8skqp   0/1     Pending             0          0s
my-dep-6b48cbf4f9-8skqp   0/1     Pending             0          0s
my-dep-6b48cbf4f9-8skqp   0/1     ContainerCreating   0          0s
my-dep-5b7868d854-4blfx   1/1     Terminating         1          22h
my-dep-6b48cbf4f9-8skqp   0/1     ContainerCreating   0          1s
my-dep-5b7868d854-4blfx   0/1     Terminating         1          22h
my-dep-5b7868d854-4blfx   0/1     Terminating         1          22h
my-dep-5b7868d854-4blfx   0/1     Terminating         1          22h
my-dep-6b48cbf4f9-8skqp   1/1     Running             0          17s
my-dep-5b7868d854-9kmm9   1/1     Terminating         1          22h
my-dep-6b48cbf4f9-d8pgs   0/1     Pending             0          0s
my-dep-6b48cbf4f9-d8pgs   0/1     Pending             0          0s
my-dep-6b48cbf4f9-d8pgs   0/1     ContainerCreating   0          0s
my-dep-5b7868d854-9kmm9   1/1     Terminating         1          22h
my-dep-6b48cbf4f9-d8pgs   0/1     ContainerCreating   0          1s
my-dep-5b7868d854-9kmm9   0/1     Terminating         1          22h
my-dep-5b7868d854-9kmm9   0/1     Terminating         1          22h
my-dep-5b7868d854-9kmm9   0/1     Terminating         1          22h
my-dep-6b48cbf4f9-d8pgs   1/1     Running             0          17s
my-dep-5b7868d854-4phcv   1/1     Terminating         1          22h
my-dep-5b7868d854-4phcv   1/1     Terminating         1          22h
my-dep-5b7868d854-4phcv   0/1     Terminating         1          22h
my-dep-5b7868d854-4phcv   0/1     Terminating         1          22h
my-dep-5b7868d854-4phcv   0/1     Terminating         1          22h
滚动回退

滚动回退建立在滚动更新之后,发现产品有Bug,需要撤回。
查看my-dep部署的历史纪录

1、第一次是部署

2、第二次是升级命令

bash 复制代码
[root@k8s-master ~]# kubectl set image deploy/my-dep  nginx=nginx:1.16.1 --record
deployment.apps/my-dep image updated
[root@k8s-master ~]# kubectl rollout history deployment/my-dep
deployment.apps/my-dep 
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image deploy/my-dep nginx=nginx:1.16.1 --record=true
#查看某个历史详情
kubectl rollout history deployment/my-dep --revision=2

#回滚(回到上次)
kubectl rollout undo deployment/my-dep

#回滚(回到指定版本)
[root@k8s-master ~]# kubectl rollout undo deploy/my-dep --to-revision=1
deployment.apps/my-dep rolled back
[root@k8s-master ~]# kubectl get deploy/my-dep -oyaml|grep image 
                f:imagePullPolicy: {}
                f:image: {}
      - image: nginx
        imagePullPolicy: Always

微服务的应用都是无状态的,对于有状态的中间件Redis、Rabbitma。未来都不直接部署pod,虽然pod才是应用的载体。我们使用工作负载使用这些pod,这样让pod能够拥有比原先更强大的功能。

无状态(Deployment):应用挂了之后,无论何时被救起来都是一样的。启动之后ip就发生了变化

有状态(StatefulForSet):应用挂了之后,无论何时被就起来是不一样的。重启之后ip稳定,数据要挂载到外面,还要加载到原来的数据。提供了稳定的存储功能。

守护进程集(DaemonSet):比如集群中有十几台机器,每台机器都产生大量日志,为每台机器都驻留一个日志收集器,每台机器的日志收集器全部收集过来放到日志中心。

Job/CronJob(任务/定时任务):比如垃圾清理工作,可以在指定时间运行。

5、Service服务发现与负载均衡

将一组 Pods 公开为网络服务的抽象方法。

当前端访问Service时的时候,能够实现负载均衡的方式实现服务的访问。
暴漏服务:把deploy部署my-dep的pod的80端口的服务暴漏到service的8000端口上统一访问。

bash 复制代码
## 删除暴漏的服务
[root@k8s-master ~]# kubectl delete service my-dep
[root@k8s-master ~]# kubectl expose deploy my-dep --port=8000 --target-port=80
service/my-dep exposed
## 查看服务,这个端口号只能在集群内访问的。
[root@k8s-master ~]# kubectl get service
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP    2d4h
my-dep       ClusterIP   10.96.12.62   <none>        8000/TCP   41s

等同于;--type=ClusterIP暴露的ip只能在集群内访问

bash 复制代码
```bash
kubectl expose deployment my-dep --port=8000 --target-port=80 --type=ClusterIP

可以在外部访问的方式:通过32604端口访问

bash 复制代码
[root@k8s-master ~]# kubectl expose deploy my-dep --port=8000 --target-port=80 --type=NodePort
service/my-dep exposed
[root@k8s-master ~]# kubectl get service
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP          2d18h
my-dep       NodePort    10.96.45.211   <none>        8000:32604/TCP   44s

查看pod标签

bash 复制代码
[root@k8s-master ~]# kubectl get pod --show-labels
NAME                      READY   STATUS    RESTARTS   AGE   LABELS
my-dep-5b7868d854-2ts4b   1/1     Running   0          59m   app=my-dep,pod-template-hash=5b7868d854
my-dep-5b7868d854-9nq7b   1/1     Running   0          59m   app=my-dep,pod-template-hash=5b7868d854
my-dep-5b7868d854-jn4p2   1/1     Running   0          59m   app=my-dep,pod-template-hash=5b7868d854

通过配置文件的方式暴露服务:通过selector的label选择出来pod暴露服务的

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  labels:
    app: my-dep
  name: my-dep
spec:
  selector:
    app: my-dep
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 80

使用tomcat创建模拟一个前端项目

bash 复制代码
[root@k8s-master ~]# kubectl create deploy my-tomcat --image=tomcat
deployment.apps/my-tomcat created

tomcat容器内部想要访问我们的后台项目,写后台的ip地址。

域名方式 复制代码
```bash
root@my-tomcat-b4c9b6565-zlssn:/usr/local/tomcat# curl 10.96.12.62:8000
root@my-tomcat-b4c9b6565-zlssn:/usr/local/tomcat# curl my-dep.default.svc:8000

6、Ingress 网关入口

service的统一网关入口。service是为一组pod服务提供一个统一集群内访问入口或外部访问的随机端口,而ingress做得是通过反射的形式对服务进行分发到对应的service上。
Ingress作为微服务的统一访问入口,将服务分配到不同的service节点。Ingress作为统一的入口,底层是nginx,根据不同的域名,交给不同的service。如order.service.com就交给orderservice.微服务之间的访问是应用层的事,应该也是走这一套的,这里属于基础设施

安装
bash 复制代码
[root@k8s-master ~]# vi ingress.yaml
[root@k8s-master ~]# kubectl apply -f ingress.yaml 
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
configmap/ingress-nginx-controller created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
service/ingress-nginx-controller-admission created
service/ingress-nginx-controller created
deployment.apps/ingress-nginx-controller created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
serviceaccount/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
[root@k8s-master ~]# kubectl get pod -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-bc4wd        0/1     Completed   0          3m29s
ingress-nginx-admission-patch-rc2fq         0/1     Completed   0          3m29s
ingress-nginx-controller-65bf56f7fc-r286m   1/1     Running     0          3m29s

ingress作为统一入口,必须有一个端口接所有的流量,也就安装形成后会形成一个服务。如下是以NodePort 方式暴漏的端口,共暴漏了两个端口。
http://xxx.xxx.xxx.xxx:31081
https://xxx.xxx.xxx.xxx:31292
80:31081/TCP,443:31292/TCP

bash 复制代码
[root@k8s-master ~]# kubectl get svc -n ingress-nginx
NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.96.178.133   <none>        80:31081/TCP,443:31292/TCP   4m34s
ingress-nginx-controller-admission   ClusterIP   10.96.91.167    <none>        443/TCP                      4m34s
使用ingress

请求的流量可以请求到任意节点上,因为每个节点都放开了这两个端口。所以我们叫端口这一层叫ingress层。ingress层的目的就是所有进来的流量都经过我处理。

  • yaml中部署了一次部署,名字叫做hello-server,有两个副本(pod),用了一个镜像叫做hello-server,工作端口是9000
  • 另外又做了一个demo,2个副本,使用nginx镜像,镜像叫做nginx-demo,这次部署的工作端口号是80
  • 还部署了服务,负载均衡网络,选中(管理)了标签app为nginx-demo的pod,名称name为nginx-demo,工作端口号是8000,代理端口号target-port是80,采用的协议是TCP
  • 另外一个服务选中(管理)了标签为hello-server的pod,名称name为hello-server,工作端口号是8000,代理端口号target-port是9000,采用的协议是TCP
如果想访问pod,就访问管理pod的服务就可以了。采用哪种方式访问呢,采用服务名+端口号的访问即可,比如:hello-server:8000或nginx-demo:8000,就可以实现访问pod。 复制代码
```bash
[root@k8s-master ~]# kubectl apply -f test.yaml 
deployment.apps/hello-server created
deployment.apps/nginx-demo created
service/nginx-demo created
service/hello-server created
yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello-server
  template:
    metadata:
      labels:
        app: hello-server
    spec:
      containers:
      - name: hello-server
        image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/hello-server
        ports:
        - containerPort: 9000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-demo
  name: nginx-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-demo
  template:
    metadata:
      labels:
        app: nginx-demo
    spec:
      containers:
      - image: nginx
        name: nginx
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-demo
  name: nginx-demo
spec:
  selector:
    app: nginx-demo
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: hello-server
  name: hello-server
spec:
  selector:
    app: hello-server
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 9000

通过在内网访问该端口的返回结果

bash 复制代码
[root@k8s-master ~]# kubectl get svc -A
NAMESPACE              NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
default                hello-server                         ClusterIP   10.96.114.8     <none>        8000/TCP                     18m
default                kubernetes                           ClusterIP   10.96.0.1       <none>        443/TCP                      3d4h
default                my-dep                               NodePort    10.96.45.211    <none>        8000:32604/TCP               9h
default                nginx-demo                           ClusterIP   10.96.218.222   <none>        8000/TCP                     18m

[root@k8s-node1 ~]# curl 10.96.114.8:8000
Hello World!

当前部署的两个部署和两个服务的代理关系如下图所示:

  • 产生了四个pod,两个service.
  • 相当于hello-server部署的两个pod会有一个hello-server的负载均衡的service
  • 相当于nginx-demo部署的两个pod会有一个nginx-demo的负载均衡的service


需求是:如果hello.atguigu.com:31405的服务转发给hello.server,如果是demo.atguigu.com:31405把请求转发给nginx-demo。下面的域名访问实现这个需求:

域名访问:创建ingress

host: "hello.atguigu.com"表示hello.atguigu.com下的所有请求,pathType是前置匹配,path表示什么路径:当前表示所有请求转发到service下,转发到哪个服务呢,name:hello-service,端口号是8000的服务。
这样就实现了将域名+资源路径的请求映射到了对应的backend服务上,服务又代理了pod。实现了整条连的映射。

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress  
metadata:
  name: ingress-host-bar
spec:
  ingressClassName: nginx
  rules:
  - host: "hello.atguigu.com"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-server
            port:
              number: 8000
  - host: "demo.atguigu.com"
    http:
      paths:
      - pathType: Prefix
        path: "/nginx"  # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
        backend:
          service:
            name: nginx-demo  ## java,比如使用路径重写,去掉前缀nginx
            port:
              number: 8000  

报错问题处理及创建ingress

bash 复制代码
[root@k8s-master ~]# kubectl apply -f ingress-rule.yaml 
Error from server (InternalError): error when creating "ingress-rule.yaml": Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io": Post "https://ingress-nginx-controller-admission.ingress-nginx.svc:443/networking/v1beta1/ingresses?timeout=10s": context deadline exceeded

[root@k8s-master ~]# kubectl get validatingwebhookconfigurations
NAME                      WEBHOOKS   AGE
ingress-nginx-admission   1          72m
[root@k8s-master ~]# kubectl delete -A ValidatingWebhookConfiguration ingress-nginx-admission
validatingwebhookconfiguration.admissionregistration.k8s.io "ingress-nginx-admission" deleted
[root@k8s-master ~]# kubectl apply -f ingress-rule.yaml 
ingress.networking.k8s.io/ingress-host-bar created
域名访问:创建ingress

察看部署成功的ingress:匹配两个域名(hello.atguigu.com,demo.atguigu.com)

bash 复制代码
[root@k8s-master ~]# kubectl get ingress
NAME               CLASS   HOSTS                                ADDRESS         PORTS   AGE
ingress-host-bar   nginx   hello.atguigu.com,demo.atguigu.com   172.26.1

这两个域名要抵达任意一台的http://:31081或者https://:31292两个端口(ingress管理的端口)

在window的域名文件下输入以下映射,即可实现域名访问服务器ip。


ingress的修改

修改ingress的端口映射:从dermo.atguigu.com ==>demo.atguigu.com:31405/ingress

bash 复制代码
[root@k8s-master ~]# kubectl get ing
NAME               CLASS   HOSTS                                ADDRESS         PORTS   AGE
ingress-host-bar   nginx   hello.atguigu.com,demo.atguigu.com   172.26.163.33   80      22h
[root@k8s-master ~]# kubectl edit ing ingress-host-bar 
ingress.networking.k8s.io/ingress-host-bar edited
yaml 复制代码
  - host: demo.atguigu.com
    http:
      paths:
      - backend:
          service:
            name: nginx-demo
            port:
              number: 8000
        path: /nginx
        pathType: Prefix

修改之后:ingress层的返回

修改之后:部署的pod的返回

负载均衡测试

在任意nginx-demo容器中的静态文件目录,增加了一个nginx文件,此时再去访问demo.atguigu.com:31081时,就会下载增加的nginx文件。

网关路径重写

重新编辑ingress有两种方式可以编辑yaml,然后apply一下,或者采用kubectl edit 命令。

bash 复制代码
## kubectl edit ing ingress-host-bar
[root@k8s-master ~]# vi ingress-rule.yaml 
[root@k8s-master ~]# kubectl apply -f ingress-rule.yaml 
ingress.networking.k8s.io/ingress-host-bar configured
yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress  
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  name: ingress-host-bar
spec:
  ingressClassName: nginx
  rules:
  - host: "hello.atguigu.com"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-server
            port:
              number: 8000
  - host: "demo.atguigu.com"
    http:
      paths:
      - pathType: Prefix
        path: "/nginx(/|$)(.*)"  # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
        backend:
          service:
            name: nginx-demo  ## java,比如使用路径重写,去掉前缀nginx
            port:
              number: 8000

现在的结果是:访问了nginx的主页。原因是路径的重写将访问路径做了重定向,当访问31081/nginx时,将请求转发到了nginx的静态资源目录.user/share/nginx/html/下的根目录下,相当于31081/nginx是一个虚路径,nginx后的路径才是真正的要访问的资源路径。这就是路径重写


这样写是下载负载均衡测试中的=创建的nginx文件

流量限制

需求:当访问limit..atguigu.com时做一个流量控制。
Exact表示精确模式,表示当访问/是才做限流控制

bash 复制代码
## 创建了一个限流的ingress
[root@k8s-master ~]# vi ingress-rule-limit.yaml
[root@k8s-master ~]# kubectl apply -f ingress-rule-limit.yaml 
ingress.networking.k8s.io/ingress-limit-rate created

添加ip映射:

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-limit-rate
  annotations:
    nginx.ingress.kubernetes.io/limit-rps: "1"
spec:
  ingressClassName: nginx
  rules:
  - host: "limit.atguigu.com"
    http:
      paths:
      - pathType: Exact
        path: "/"
        backend:
          service:
            name: nginx-demo
            port:
              number: 8000

测试结果:间歇性的不可访问界面。

最然做了限流处理,但是还是能将请求青映射到4个pod上,能够返回pod内的内容。因为limit没有做重定向,所以通过limit的url访问url时,无法下载nginx文件

网络模型

存储抽象

docker 方式的挂载在外面便于修改数据

存在问题:k8s中,如果仍旧采用这种模式,如果pod宕机了,在另外一个pod上重启一个pod,所挂在的新的pod/tmp时没有数据的,就存在数据不一致的问题。而且数据量庞大的问题也很难解决

问题解决方案:存储层现在交给k8s存储层了,如果需要挂载什么数据,直接找k8s。即使pod宕机也能再次将pod关联到重启的pod上。

k8s在存储层可以采用不同的方案,比如NFS(网络存储系统),是将文件统一管理到一处,同时会做一个数文件的备份目录,备份目录之间会做文件的同步更新,防止存储层炸了后数据的丢失。所以任意一个节点的数据是同步的。

搭建NFS网络文件存储系统

指定任意一台机器为NFS Server,比如指定K8S master为Server

bash 复制代码
#所有机器安装
yum install -y nfs-utils
主节点

指定暴露目录/nfs/data/,并且以非安全的方式进行暴露,独写的方式进行同步

bash 复制代码
## 在master节点暴漏一个nfs目录
[root@k8s-master ~]# echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
[root@k8s-master ~]# mkdir /nfs/data
[root@k8s-master ~]# mkdir -p /nfs/data
## rpc远程同步调用的服务。
[root@k8s-master ~]# systemctl enable rpcbind --now
## 开机启动nfs服务器
[root@k8s-master ~]# systemctl enable nfs-server --now
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.
[root@k8s-master ~]# exportfs -r
# 检查nfs服务器是否设置正确路径
[root@k8s-master ~]# exportfs
/nfs/data       <world>
让其他节点同步NFS

任何一个节点对文件修改,都会同步。

bash 复制代码
## 使用私有网卡的地址。ip a的eth0
## 检查命令
[root@k8s-node1 ~]# showmount -e 172.26.163.34
Export list for 172.26.163.34:
/nfs/data *
#执行以下命令挂载 nfs 服务器上的共享目录到本机路径 /root/nfsmount
mkdir -p /nfs/data
## 挂在同步master中的内容。远程服务器的ip:目录:172.26.163.34:/nfs/data

mount -t nfs 172.26.163.34:/nfs/data /nfs/data
# 写入一个测试文件
echo "hello nfs server" > /nfs/data/test.txt
原生方式挂载数据

名字为nginx的pod,内部的mountPath: /usr/share/nginx/html目录,映射到服务器的/nfs/data/nginx-pv目录

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-pv-demo
  name: nginx-pv-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-pv-demo
  template:
    metadata:
      labels:
        app: nginx-pv-demo
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
      volumes:
        - name: html
          nfs:
            server: 172.26.163.34
            path: /nfs/data/nginx-pv

部署nginx文件绑定的pod

bash 复制代码
[root@k8s-master ~]# vi deploy.yaml
[root@k8s-master ~]# kubectl apply -f deploy.yaml 
deployment.apps/nginx-pv-demo created
[root@k8s-master ~]# kubectl get pod
NAME                             READY   STATUS              RESTARTS   AGE
hello-server-6cbb679d85-m5nsc    1/1     Running             2          43h
hello-server-6cbb679d85-pcrnj    1/1     Running             2          43h
my-dep-5b7868d854-2ts4b          1/1     Running             4          2d19h
my-dep-5b7868d854-kmw8g          1/1     Running             3          2d5h
my-dep-5b7868d854-wrp6f          1/1     Running             3          2d5h
my-tomcat-b4c9b6565-zlssn        1/1     Running             4          2d18h
nginx-demo-7d56b74b84-2pfn4      1/1     Running             2          43h
nginx-demo-7d56b74b84-n4gff      1/1     Running             2          43h
nginx-pv-demo-8699c67f95-95wd6   0/1     ContainerCreating   0          13s
nginx-pv-demo-8699c67f95-kdv5j   0/1     ContainerCreating   0          13s
bash 复制代码
###  当在主节点向index.html输入11112222后,在任意容器中都能看到输入的数据。
root@nginx-pv-demo-8699c67f95-95wd6:/# cd /usr/share/nginx/html/
root@nginx-pv-demo-8699c67f95-95wd6:/usr/share/nginx/html# ls
index.html
root@nginx-pv-demo-8699c67f95-95wd6:/usr/share/nginx/html# cat index.html 
11112222
root@nginx-pv-demo-8699c67f95-95wd6:/usr/share/nginx/html# 
PV/PVC

原生方式存在的问题:①每个pod内的挂载的目录需要手动创建②当部署被删除后,文件未删除③每个pod所使用的目录文件的大小未做限制。

PV:持久卷(Persistent Volume),将应用需要持久化的数据保存到指定位置。空间

PVC:持久卷申明(Persistent Volume Claim),申明需要使用的持久卷规格。如果pod想挂载数据了,在pod上写一个申请书(PVC),按照合适的PV池给pod分配空间。避免空间的浪费。如果pod删除了,连带着pod所挂载的pvc也可以被删除,pvc中的pv也就被删除了。如果pvc未被删除,pv空间不会被删除。

PV池:需要多少空间,先声明好,提前供应规划好,形成一个池。而不是需要多少空间我动态创建。
PV的回收策略:①保留,该策略允许手动回收资源,当删除PVC时,PV仍然存在,PV被视为已释放,管理员可以手动回收卷。②删除,如果Volume插件支持,删除PVC时会同时删除PV,动态卷默认为Delete,目前支持Delete的存储后端包括AWS EBS。③回收。可以被PVC重复使用。rm-rf 清理该PV

bash啊发[root@k8s-master 复制代码
index.html
[root@k8s-master nginx-pv]# cd ~
[root@k8s-master ~]# kubectl delete -f deploy.yaml 
deployment.apps "nginx-pv-demo" deleted
[root@k8s-master ~]# cd /nfs/data/
[root@k8s-master data]# cd ./nginx-pv/
[root@k8s-master nginx-pv]# ls
index.htl
  • 创建pv池
bash 复制代码
#nfs主节点
mkdir -p /nfs/data/01
mkdir -p /nfs/data/02
mkdir -p /nfs/data/03
  • 创建pv

---分隔符

kind: PersistentVolume 类型是PV

capacity:storage: 10M 限制文件的大小

yaml 复制代码
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv01-10m
spec:
  capacity:
    storage: 10M
  accessModes:
    - ReadWriteMany
  storageClassName: nfs
  nfs:
    path: /nfs/data/01
    server: 172.26.163.34
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv02-1gi
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  storageClassName: nfs
  nfs:
    path: /nfs/data/02
    server: 172.26.163.34
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv03-3gi
spec:
  capacity:
    storage: 3Gi
  accessModes:
    - ReadWriteMany
  storageClassName: nfs
  nfs:
    path: /nfs/data/03
    server: 172.26.163.34
bash 复制代码
[root@k8s-master ~]# kubectl apply -f pv.yaml 
persistentvolume/pv01-10m created
persistentvolume/pv02-1gi created
persistentvolume/pv03-3gi created
[root@k8s-master ~]# kubectl get persistentvolume
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv01-10m   10M        RWX            Retain           Available           nfs                     2m27s
pv02-1gi   1Gi        RWX            Retain           Available           nfs                     2m27s
pv03-3gi   3Gi        RWX            Retain           Available           nfs                     2m27s
[root@k8s-master ~]# vi pvc.yaml
[root@k8s-master ~]# kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv01-10m   10M        RWX            Retain           Available           nfs                     8m22s
pv02-1gi   1Gi        RWX            Retain           Available           nfs                     8m22s
pv03-3gi   3Gi        RWX            Retain           Available           nfs                     8m22s
[root@k8s-master ~]# kubectl apply -f pvc.yaml 
persistentvolumeclaim/nginx-pvc created
## c创建好后,就被绑定了。
[root@k8s-master ~]# kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM               STORAGECLASS   REASON   AGE
pv01-10m   10M        RWX            Retain           Available                       nfs                     8m56s
pv02-1gi   1Gi        RWX            Retain           Bound       default/nginx-pvc   nfs                     8m56s
pv03-3gi   3Gi        RWX            Retain           Available                       nfs                     8m56s
  • pvc创建与绑定

storageClassName要和上面的storageClassName保持一致。在storageClassName下找一个合适的空间

bash 复制代码
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: nginx-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 200Mi
  storageClassName: nfs
  • pvc删除

删除后处于Released,空间还未完全释放。此时如果再申请空间,会分配其他的空间。pv02-1gi会一直处于Released状态,需要编辑pv02-1gi资源,删除claimRef段落就可以变成可用了

bash 复制代码
[root@k8s-master ~]# kubectl delete -f pvc.yaml 
persistentvolumeclaim "nginx-pvc" deleted
[root@k8s-master ~]# kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM               STORAGECLASS   REASON   AGE
pv01-10m   10M        RWX            Retain           Available                       nfs                     10m
pv02-1gi   1Gi        RWX            Retain           Released    default/nginx-pvc   nfs                     10m
pv03-3gi   3Gi        RWX            Retain           Available                       nfs                     10m
[root@k8s-master ~]# kubectl apply -f pvc.yaml 
persistentvolumeclaim/nginx-pvc created
[root@k8s-master ~]# kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM               STORAGECLASS   REASON   AGE
pv01-10m   10M        RWX            Retain           Available                       nfs                     15m
pv02-1gi   1Gi        RWX            Retain           Released    default/nginx-pvc   nfs                     15m
pv03-3gi   3Gi        RWX            Retain           Bound       default/nginx-pvc   nfs                     15m
[root@k8s-master ~]# kubectl get pvc
NAME        STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nginx-pvc   Bound    pv03-3gi   3Gi        RWX            nfs            74s
  • 通过PC创建绑定pod

我要用的空间是这个空间申请书的空间。

bash 复制代码
[root@k8s-master ~]# vi dep02.yaml
[root@k8s-master ~]# kubectl apply -f dep02.yaml 
deployment.apps/nginx-deploy-pvc created
[root@k8s-master ~]# kubectl get pod
NAME                                READY   STATUS              RESTARTS   AGE
hello-server-6cbb679d85-m5nsc       1/1     Running             2          44h
hello-server-6cbb679d85-pcrnj       1/1     Running             2          44h
my-dep-5b7868d854-2ts4b             1/1     Running             4          2d21h
my-dep-5b7868d854-kmw8g             1/1     Running             3          2d6h
my-dep-5b7868d854-wrp6f             1/1     Running             3          2d6h
my-tomcat-b4c9b6565-zlssn           1/1     Running             4          2d20h
nginx-demo-7d56b74b84-2pfn4         1/1     Running             2          44h
nginx-demo-7d56b74b84-n4gff         1/1     Running             2          44h
nginx-deploy-pvc-79fc8558c7-2fz2z   1/1     Running             0          6s
nginx-deploy-pvc-79fc8558c7-x82v5   0/1     ContainerCreating   0          6s
yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deploy-pvc
  name: nginx-deploy-pvc
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-deploy-pvc
  template:
    metadata:
      labels:
        app: nginx-deploy-pvc
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
      volumes:
        - name: html
          persistentVolumeClaim:
            claimName: nginx-pvc
  • pod,pvc,pv关系

pvc的状态是Bound,说明有pod绑定这个pvc。pvc跟volume(pv03-3gi)绑定了。pv中的pv03-3gi中的目录下就是数据

bash 复制代码
[root@k8s-master ~]# kubectl get pvc,pv
NAME                              STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/nginx-pvc   Bound    pv03-3gi   3Gi        RWX            nfs            8m9s

NAME                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM               STORAGECLASS   REASON   AGE
persistentvolume/pv01-10m   10M        RWX            Retain           Available                       nfs                     23m
persistentvolume/pv02-1gi   1Gi        RWX            Retain           Released    default/nginx-pvc   nfs                     23m
persistentvolume/pv03-3gi   3Gi        RWX            Retain           Bound       default/nginx-pvc   nfs                     23m
  • 静态供应:pvc需要空间只能从pv池中选择
  • 动态供应:pv会在一个地方自动的创建一个想要空间大小的空间。不需要手动创建好了
ConfigMap 配置文件挂载
  • 创建ConfigMap 创建的配置集实际上是在etcd中存着
bash 复制代码
[root@k8s-master 03]# vi redis.conf
[root@k8s-master 03]# kubectl create cm redis-conf --from-file=redis.conf
configmap/redis-conf created
[root@k8s-master 03]# kubectl get cm
NAME               DATA   AGE
kube-root-ca.crt   1      5d
redis-conf         1      9s
[root@k8s-master 03]# rm -rf redis.conf 

查看数据集内容

data:key | configContent 。key是文件名。

bash 复制代码
[root@k8s-master 03]# kubectl get cm redis-conf -oyaml
apiVersion: v1
data:
  redis.conf: |
    appendonly yes
kind: ConfigMap
metadata:
  creationTimestamp: "2022-09-17T11:12:02Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        .: {}
        f:redis.conf: {}
    manager: kubectl-create
    operation: Update
    time: "2022-09-17T11:12:02Z"
  name: redis-conf
  namespace: default
  resourceVersion: "141413"
  uid: 6e1eeba3-ef19-42ee-bb52-4bd38d592e89
  • 使用配置集中的内容创建pod
bash 复制代码
[root@k8s-master ~]# kubectl apply -f redis.yaml 
pod/redis created
[root@k8s-master ~]# kubectl get pod 
NAME                                READY   STATUS    RESTARTS   AGE
hello-server-6cbb679d85-m5nsc       1/1     Running   2          45h
hello-server-6cbb679d85-pcrnj       1/1     Running   2          45h
my-dep-5b7868d854-2ts4b             1/1     Running   4          2d22h
my-dep-5b7868d854-kmw8g             1/1     Running   3          2d7h
my-dep-5b7868d854-wrp6f             1/1     Running   3          2d7h
my-tomcat-b4c9b6565-zlssn           1/1     Running   4          2d21h
nginx-demo-7d56b74b84-2pfn4         1/1     Running   2          45h
nginx-demo-7d56b74b84-n4gff         1/1     Running   2          45h
nginx-deploy-pvc-79fc8558c7-2fz2z   1/1     Running   0          55m
nginx-deploy-pvc-79fc8558c7-x82v5   1/1     Running   0          55m
redis                               1/1     Running   0          16s

command 是启动命令,/redis-master/redis.conf是指容器内部的位置。volumeMounts指卷挂载,共挂载了两个:

①名字为data的挂载,容器内目录是/data,映射的宿主机目录是/redis-master。下面volumes下名为data做了详细说明。volumes下empty:{}空的工作目录。

②名为config的配置集。映射的宿主机目录是/redis-master,在volume中详细说明。映射给configMap,configMap中通过name(redis-conf)映射到了cm中名为redis-conf的cm配置。又通过item中的redis.conf映射到redis.conf的配置。path表示mountPath下的子路径。

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  containers:
  - name: redis
    image: redis
    command:
      - redis-server
      - "/redis-master/redis.conf"  #指的是redis容器内部的位置
    ports:
    - containerPort: 6379
    volumeMounts:
    - mountPath: /data
      name: data
    - mountPath: /redis-master
      name: config
  volumes:
    - name: data
      emptyDir: {}
    - name: config
      configMap:
        name: redis-conf
        items:
        - key: redis.conf
          path: redis.conf

容器中查看

bash 复制代码
root@redis:/data# cd /redis-master/redis.conf 
bash: cd: /redis-master/redis.conf: Not a directory
root@redis:/data# cd /redis-master/
root@redis:/redis-master# cat redis.conf 
appendonly yes
  • 编辑redis配置文件

在外面把配置文件改了,容器内部会跟着改变。cm改了之后容器内部也会跟着改。此时重启pod密码就会生效。

配置值未更改,因为需要重新启动 Pod 才能从关联的 ConfigMap 中获取更新的值。

原因:我们的Pod部署的中间件自己本身没有热更新能力

bash 复制代码
[root@k8s-master ~]# kubectl get cm
NAME               DATA   AGE
kube-root-ca.crt   1      5d1h
redis-conf         1      42m
[root@k8s-master ~]# kubectl edit cm redis-conf
configmap/redis-conf edited
root@redis:/redis-master# cat redis.conf 
appendonly yes
requirepass Test1127?!
root@redis:/redis-master# 
[root@k8s-master ~]# kubectl exec -it redis -- redis-cli
127.0.0.1:6379> CONFIG GET appendonly
1) "appendonly"
2) "yes"
127.0.0.1:6379> CONFIG GET requirepass
1) "requirepass"
2) ""

7、Secret

Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 将这些信息放在 secret 中比放在 Pod 的定义或者 容器镜像 中来说更加安全和灵活。

我们都是直接拉去共有镜像。

公司私有的镜像仓库:存放所有的写的微服务的jar包,如果从私有仓库拉取jar需要登陆。如果把登陆账号密码写到每个pod中,不安全。如果采用k8ssecret的方式把docker的账号密码保存起来,如果以后想拉取镜像时,直接拉取就可以了。

没有账号密码的情况下下载不下来

bash 复制代码
[root@k8s-master ~]# docker pull xiaguangpei/java-demo:v1.0
Error response from daemon: pull access denied for xiaguangpei/java-demo, repository does not exist or may require 'docker login': denied: requested access to the resource is denied

错误范例

bash 复制代码
apiVersion: latest
kind: Pod
metadata:
  name: xgpnginx
spec:
  containers:
  - name: xgpnginx
    image: xiaguangpei/xgpnginx

登陆私有账号

##命令格式

kubectl create secret docker-registry regcred

--docker-server=<你的镜像仓库服务器>

--docker-username=<你的用户名>

--docker-password=<你的密码>

--docker-email=<你的邮箱地址>

bash 复制代码
[root@k8s-master ~]# kubectl create secret docker-registry xiaguangpei-docker \
> --docker-username=xiaguangpei \
> --docker-password=Test1127?! \
> --docker-email=987224389@qq.com
secret/xiaguangpei-docker created

base64加密

bash 复制代码
[root@k8s-master ~]# kubectl get secret
NAME                  TYPE                                  DATA   AGE
default-token-ntj7s   kubernetes.io/service-account-token   3      5d2h
xiaguangpei-docker    kubernetes.io/dockerconfigjson        1      44s
[root@k8s-master ~]# kubectl get secret xiaguangpei-docker -oyaml
apiVersion: v1
data:
  .dockerconfigjson: 
  xxxxxxxxxxxxxxxxxxx
kind: Secret
metadata:
  creationTimestamp: "2022-09-17T12:40:10Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        .: {}
        f:.dockerconfigjson: {}
      f:type: {}
    manager: kubectl-create
    operation: Update
    time: "2022-09-17T12:40:10Z"
  name: xiaguangpei-docker
  namespace: default
  resourceVersion: "149588"
  uid: 81421418-5482-4c22-a045-924ebbddd78f
type: kubernetes.io/dockerconfigjson

真正的拉取私有云的镜像的方法

bash 复制代码
[root@k8s-master ~]# vi java-demo.yaml
[root@k8s-master ~]# kubectl apply -f java-demo.yaml 
pod/java-demo created
yaml 复制代码
apiVersion: v1.0
kind: Pod
metadata:
  name: java-demo
spec:
  containers:
  - name: java-demo
    image: xiaguangpei/java-demo:v1.0
  imagePullSecrets:
  - name: xiaguangpei-docker
相关推荐
handler011 小时前
TCP(传输控制协议)核心机制与底层原理
linux·网络·c++·笔记·网络协议·tcp/ip·操作系统
运维全栈笔记1 小时前
Harbor生产级部署实战:PostgreSQL+Redis+MinIO全解耦架构详解
linux·运维·服务器·笔记·架构·kubernetes·k8s
Lochor Lee1 小时前
C++学习笔记——输入输出的格式
c++·笔记·学习
babe小鑫1 小时前
2026数字营销专业人士学习数据分析的必要性
学习·数据挖掘·数据分析
吃好睡好便好1 小时前
在Matlab中绘制二维等高线图
开发语言·人工智能·学习·算法·matlab
xian_wwq2 小时前
【学习笔记】探讨大模型应用安全建设系列——顶层规划:如何推动公司级大模型安全建设-1
笔记·学习·安全·ai
问心无愧05132 小时前
ctf show web入门 89
android·前端·笔记
only-lucky2 小时前
QML深入学习三(JavaScript用法)
笔记
SPC的存折2 小时前
22、K8S-Helm
云原生·容器·kubernetes