一、为什么要学习K8S
Kubernetes 为你提供了一个可弹性运行分布式系统的框架。 Kubernetes 会满足你的扩展要求、故障转移你的应用、提供部署模式等。
负载均衡
自动部署和回滚
自我修复
**二、**架构图

三、如何搭建K8S集群
3.1安装K8S
|----|---------|-----------------|
| 序号 | 节点名称 | IP |
| 1 | master1 | 192.168.200.131 |
| 2 | worker1 | 192.168.200.132 |
| 3 | worker2 | 192.168.200.133 |
bash
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 第一步:安装ntp服务
yum -y install ntp
# 第二步:开启开机启动服务
systemctl enable ntpd
# 第三步:启动服务
systemctl start ntpd
# 第四步:更改时区
timedatectl set-timezone Asia/Shanghai
# 第五步:启用ntp同步
timedatectl set-ntp yes
# 第六步:同步时间
ntpq -p
# 移除之前版本
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 配置镜像源
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 指定版本安装 docker
yum install -y docker-ce-20.10.7 docker-ce-cli-20.10.7 containerd.io-1.4.6
# 查看 docker 版本
[root@localhost ~]# docker -v
Docker version 20.10.7, build f0df350
# 设置开机自启并启动
systemctl enable docker --now
# 设置镜像加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.1ms.run",
"https://ccr.ccs.tencentyun.com",
"https://hub.xdark.top",
"https://hub.fast360.xyz",
"https://docker-0.unsee.tech",
"https://docker.xuanyuan.me",
"https://docker.tbedu.top",
"https://docker.hlmirror.com",
"https://doublezonline.cloud",
"https://docker.melikeme.cn",
"https://image.cloudlayer.icu",
"https://dislabaiot.xyz",
"https://freeno.xyz",
"https://docker.kejilion.pro"
],
"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
3.2 配置三台机器主机名
hostnamectl set-hostname k8s-master
hostnamectl set-hostname k8s-worker1
hostnamectl set-hostname k8s-worker2
3.3 配置预备环境
bash
# 在各个机器上都要设置
# 将 SELinux 设置为 permissive 模式
•enforcing:强制模式,代表 SELinux 运作中,且已经正确的开始限制 domain/type 了;
•permissive:宽容模式:代表 SELinux 运作中,不过仅会有警告讯息并不会实际限制 domain/type 的存取。这种模式可以运来作为 SELinux 的 debug 之用;
•disabled:关闭,SELinux 并没有实际运作。
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
#关闭swap 占用
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
# 可以使用命令查看是否关闭swap分区
free -m
#允许 iptables 检查桥接流量,也能统计Ip6的数据流量
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
# 使配置生效
sudo sysctl --system
3.4 安装kubelet、kubeadm、kubectl
bash
#配置k8s的yum源地址
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
EOF
#安装 kubelet,kubeadm,kubectl
sudo yum install -y kubelet-1.20.9 kubeadm-1.20.9 kubectl-1.20.9
#启动kubelet
sudo systemctl enable kubelet
sudo systemctl start kubelet
sudo systemctl status kubelet
3.5 所有机器,配置域名映射
bash
#所有机器添加master域名映射,以下需要修改为自己的,IP:主节点的IP
echo "192.168.200.131 k8s-master" >> /etc/hosts
# 修改每台主机的hosts 将每个服务器都要写上 master worker1 worker2
vi /etc/hosts
192.168.200.131 k8s-master
192.168.200.132 k8s-worker1
192.168.200.133 k8s-worker2
# 如果添加成功 使用 ping k8s-master 能 ping 通
[root@bogon ~]# ping k8s-master
PING cluster-endpoint (192.168.200.181) 56(84) bytes of data.
64 bytes from cluster-endpoint (192.168.200.181): icmp_seq=1 ttl=64 time=0.584 ms
64 bytes from cluster-endpoint (192.168.200.181): icmp_seq=2 ttl=64 time=0.422 ms
# 上传镜像,并运行对应的shell 脚本,完成镜像导入!
3.6 主节点初始化
bash
# 主节点初始化
# --image-repository 使用阿里云的镜像仓库
# 192.168.200.131 : 主节点的IP
# k8s-cluster : 跟3.5步骤的域名映射一致
# 192.168.0.0 : 网络插件IP,如果你的电脑网段是192.168.xxx.xxx,那么这个IP需要更换
kubeadm init \
--apiserver-advertise-address=192.168.200.131 \
--control-plane-endpoint=k8s-master \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.20.9 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=172.32.0.0/16
# 命令注释:
# 这是一个用于初始化Kubernetes集群的命令,具体参数的含义如下:
--apiserver-advertise-address: 指定API服务器的公网IP地址。
--control-plane-endpoint: 指定控制平面节点的域名或IP地址。
--image-repository: 指定镜像仓库的地址。
--kubernetes-version: 指定要安装的Kubernetes版本。
--service-cidr: 指定服务网络的CIDR块,定义kubernetes服务的虚拟IP地址段,所有Service的ClusterIP将从该网段分配。
--pod-network-cidr: 指定Pod网络的CIDR块,定义Pod所在的网络地址,需与后续部署的网络查看配置的网段一致,否则Pod之间无法通信。
#所有网络范围不重叠
# 常见问题: /proc/sys/net/ipv4/ip_forward contents are not set to 1z
# 将master节点-work节点都执行
echo "1" > /proc/sys/net/ipv4/ip_forward
# 常见问题: modprobe: FATAL: Module nf_conntrack_ipv4 not found
cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- br_netfilter
EOF
# 所有网络范围不重叠
# 操作成功日志(保存好日志)
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 k8s-cluster:6443 --token llqz9p.qbgs9kmckdv3bem4 \
--discovery-token-ca-cert-hash sha256:7d486d205dbe6c7a7463c5c4954dcb36afd092befcbd480b9b1bf92199081948 \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join k8s-cluster:6443 --token llqz9p.qbgs9kmckdv3bem4 \
--discovery-token-ca-cert-hash sha256:7d486d205dbe6c7a7463c5c4954dcb36afd092befcbd480b9b1bf92199081948
保存好上面的启动成功的日志
3.7 部署网络插件
bash
curl https://docs.projectcalico.org/v3.20/manifests/calico.yaml -O
# 注意,主节点初始时,如果修改 --pod-network-cidr=192.168.0.0/16
# 原有配置是注释掉的 3888 3889
# - name: CALICO_IPV4POOL_CIDR
# value: "192.168.0.0/16"
# calico.yaml ip 也需要修改
- name: CALICO_IPV4POOL_CIDR
value: "172.32.0.0/16"
#应用这个配置文件
kubectl apply -f calico.yaml
3.8 创建worker节点
使用上面保存的日志(不要用我的,连不上的)
bash
kubeadm join k8s-cluster:6443 --token llqz9p.qbgs9kmckdv3bem4 \
--discovery-token-ca-cert-hash sha256:7d486d205dbe6c7a7463c5c4954dcb36afd092befcbd480b9b1bf92199081948
问题解决:
bash
# 如果出现这个错误,解决方案
[ERROR DirAvailable--etc-kubernetes-manifests]: /etc/kubernetes/manifests is not empty
[ERROR FileAvailable--etc-kubernetes-kubelet.conf]: /etc/kubernetes/kubelet.conf already exists
[ERROR Port-10250]: Port 10250 is in use
[ERROR FileAvailable--etc-kubernetes-pki-ca.crt]: /etc/kubernetes/pki/ca.crt already exists
kubeadm reset
令牌过期:
bash
[root@localhost ~]# kubeadm token create --print-join-command
kubeadm join cluster-kubendpoint:6443 --token k3z6hm.7dptca591imod2mn --discovery-token-ca-cert-hash sha256:d66cffb305f0274c9984ef1fe1447245655d3094922cbcb61dbd64ada619455f
3.9 验证集群状态
bash
[root@k8s-master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane,master 104m v1.20.9
k8s-worker1 Ready <none> 101m v1.20.9
k8s-worker2 Ready <none> 101m v1.20.9
bash
kubectl get node # 查询节点状态
kubectl get pod -A #查询K8S部署的所有pod
kubectl get pod -A -o wide #打印详细信息,查看pod在哪个节点部署
kubectl apply -f 部署文件.yaml # 向K8S中部署资源
kubectl version # K8S版本
3.10 部署k8s的可视化界面(deshboard)
在浏览器访问:
https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml
vi recommended.yaml #复制粘贴上述配置文件
bash
将配置文件中的这两个镜像
image: kubernetesui/dashboard:v2.3.1
image: kubernetesui/metrics-scraper:v1.0.6
替换为下面的两个
image: registry.cn-hangzhou.aliyuncs.com/google_containers/dashboard:v2.3.1
image: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-scraper:v1.0.6
kubectl apply -f recommended.yaml
修改服务网络 [root@localhost ~]# kubectl edit svc kubernetes-
bash
# 修改服务网络
[root@localhost ~]# kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
# 文件第29行 type: ClusterIP 改为 type: NodePort
# 查询对外暴露的端口
[root@localhost ~]# kubectl get svc -A |grep kubernetes-dashboard
kubernetes-dashboard dashboard-metrics-scraper ClusterIP 10.96.22.70 <none> 8000/TCP 31m
kubernetes-dashboard kubernetes-dashboard NodePort 10.96.61.107 <none> 443:30282/TCP 31m
记住这里的443:30282/TCP,咱们肯定不一样
测试访问:
https://192.168.200.131:30282 #端口改为上面的端口号
创建访问账号 才能访问
bash
#创建访问账号,准备一个yaml文件; vi dash-user.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
kubectl apply -f dash-user.yaml
获取令牌
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
开机自启动:
systemctl enable kubelet
systemctl enable docker
systemctl disable firewalld
核心实战
4.1 资源创建方式
在Kubernetes(k8s)中,所有的内容都被抽象为资源,用户通过操作这些资源来管理Kubernetes集群。
- Pod资源
- Service资源
- Volume资源
4.1.1 命令行
使用以下语法从终端窗口运行 kubectl 命令:
bash
kubectl [command] [TYPE] [NAME] [flags]
其中 command、 TYPE、 NAME 和 flags 分别是:
- command:指定要对一个或多个资源执行的操作 ,例如 create、get、describe、delete。
- TYPE:指定资源类型。资源类型不区分大小写, 可以指定单数、复数或缩写形式。
- NAME:指定资源的名称 。名称区分大小写。 如果省略名称,则显示所有资源的详细信息。例如:kubectl get pods。
- flags: 指定可选的参数。例如,使用 -s 或 --server 参数指定 Kubernetes API 服务器的地址和端口。
常用命令
bash
# 创建 命名空间
kubectl create ns dev
# 创建 Nginx 服务器
kubectl run pod --image=nginx -n dev
# 查询default命名空间中pod
kubectl get pod
# 查询所有命名空间中pod
kubectl get pod -A
# 查询指定命名空间中pod
kubectl get pod -n dev
# 删除 pod
kubectl delete pod pod -n dev
4.1.2 YAML
bash
# 创建YAML文件
vim nginx.yaml
# 编辑文件
apiVersion: v1
kind: Namespace
metadata:
name: dev
---
apiVersion: v1
kind: Pod
metadata:
name: mynginx
namespace: dev
spec:
containers:
- name: nginx-containers
image: nginx
# 创建 pod
kubectl apply -f nginx.yaml
# 删除 pod
kubectl delete -f nginx.yaml
4.2 Namespace
Namespace是K8S中的一种非常重要资源,它的主要作用是用来实现 资源隔离。可以隔离不同用户、项目或环境之间的资源,以确保资源的合理使用和安全性。Namespace可以用于区分不同的用户、租户、环境和项目,以便更好地管理集群资源。在创建pod时,可以指定pod到特定的Namespace。
K8S提供了几个默认的Namespace,例如default、kube-system和kube-public。default命名空间用于未指定Namespace的对象,kube-system主要用于运行系统级资源,存放Kubernetes一些组件的。
命令方式操作命名空间
bash
kubectl get ns
kubectl create ns hello
kubectl delete ns hello
YAML方式操作命令空间
bash
# 创建YAML文件
vim ns-dev.yaml
# 编辑文件
apiVersion: v1 # 版本信息
kind: Namespace # 资源类型
metadata: # 元数据的意思
name: dev
# 创建命名空间
kubectl apply -f ns-dev.yaml
# 删除命名空间
kubectl delete -f ns-dev.yaml
注意:删除命名空间时,该命名空间下的所有资源都会被删除
4.3 Pod
Pod 是可以在 K8S中创建和管理的、最小的可部署的计算单元。我们可以理解Pod就是容器的封装,一个Pod中可以有 多个容器。
4.3.1 Pod基本操作
bash
# 创建 Pod
kubectl run mynginx --image=nginx
# 查看default名称空间的Pod ,指定-A属性查询所有名称空间下的Pod
kubectl get pod
# 描述
kubectl describe pod 你自己的Pod名字
# 删除
kubectl delete pod Pod名字
# 查看Pod的运行日志
kubectl logs Pod名字
# 每个Pod - k8s都会分配一个ip
kubectl get pod -owide
集群中的任意一个机器以及任意的应用都能通过Pod分配的IP来访问这个Pod,截止目前,我们创建的Pod还不能外部访问
4.3.2 创建多容器Pod
创建单容器Yaml示例
bash
# 单个容器描述文件 vi mynginx.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: mynginx
name: mynginx
# namespace: default
spec:
containers:
- image: nginx
name: mynginx
创建多容器Yaml示例
bash
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp
name: myapp
spec:
containers:
- image: nginx
name: nginx
- image: tomcat:8.5.68
name: tomcat
使用命令查看会发现有两个容器被创建
root@k8s-master \~\]# kubectl describe pod myapp
##### **4.3.3 Pod内部原理**

##### **4.3.4 Pod自我恢复演示**
了解 ,其实我们通过停止或者删除的方式模拟容器崩溃,K8S会帮我们修复容器
##### **4.3.5 Pod资源配置**
容器中的程序在运行时需要占用一定的资源,如CPU和内存等。如果不限制某个容器的资源使用,它可能会消耗大量的资源,导致其他容器无法正常运行。为了解决这个问题,Kubernetes提供了资源配额机制,主要通过"resources"选项来实现。该机制包含两个子选项:
* limits:用于限制容器运行时的最大资源占用。当容器的资源使用超过这个限制时,容器将被终止并重新启动。
* requests:用于设置容器所需的最小资源。如果环境中提供的资源不足,容器将无法启动。
```bash
apiVersion: v1
kind: Pod
metadata:
name: pod-test
spec:
containers:
- name: nginx
image: nginx
resources: # 资源配额
limits: # 限制上限
cpu: "1"
memory: "1Gi"
requests: # 限制下限
cpu: "1"
memory: "100Mi"
```
#### **4.4 Deployment**
Deployment代表执行一次部署, **可以部署多个pod** 、 **控制Pod**,使Pod拥有多副本、自愈、扩缩容等能力

##### **4.4.1 常规操作**
```bash
# 创建一次部署
kubectl create deployment mytomcat --image=tomcat:8.5.68
# 创建一个3个副本的部署
kubectl create deployment my-dep --image=nginx --replicas=3
# 获取部署信息
kubectl get deployment
kubectl get deploy
# 删除部署
kubectl delete deployment mytomcat
```
Yaml创建部署
vi mynginxapp.yaml
```bash
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: mynginx
name: mynginxapp
spec:
replicas: 1
selector:
matchLabels:
app: mynginx
template:
metadata:
labels:
app: mynginx
spec:
containers:
- image: nginx
name: nginx
```
##### **4.4.2 自愈\&故障转移**
自愈是指k8s帮我们修复应用,比如我们pod内部容器,宕机了,这时候k8s感知到会尝试重启。
故障转移,是指我们k8s集群可能有一台机器宕机了,这个时候,k8s帮我们把宕机节点应用重新部署到其他worker节点上。
```bash
# 演示pod、deployment 区别
# deployment 部署一个tomcat
kubectl create deployment mytomcat1 --image=tomcat:8.5.68
# pod
kubectl run mynginx --image=nginx
[root@k8s-master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
mynginx 1/1 Running 0 34s
mytomcat1-7c9898f454-pl9kz 1/1 Running 0 3m59s
kubectl delete pod mynginx
kubectl delete pod mytomcat1-7c9898f454-pl9kz
```
##### **4.4.3 多副本**
```bash
kubectl create deployment my-dep --image=nginx --replicas=3
# 通过yaml文件可以指定多副本
replicas: 3
# 监控pod -删除一个pod的时候,会自动创建一个pod
watch -n 1 kubectl get pod
```
##### **4.4.4 扩缩容pod**
> kubectl scale --replicas=5 deployment/my-dep
##### **4.4.5 滚动更新**
灰度发布:
```bash
kubectl set image deployment/my-dep nginx=nginx:1.16.1 --record
kubectl rollout status deployment/my-dep
```
##### **4.4.6 版本回退**
```bash
#历史记录
kubectl rollout history deployment/my-dep
#查看某个历史详情
kubectl rollout history deployment/my-dep --revision=2
#回滚(回到上次)
kubectl rollout undo deployment/my-dep
#回滚(回到指定版本)
kubectl rollout undo deployment/my-dep --to-revision=2
```
#### **4.5 Service**
在Kubernetes中,Pod是运行应用程序的容器,然而,由于Pod的 **IP地址是动态分配的**,因此直接使用Pod的IP地址进行服务访问并不方便。为了解决这个问题,Kubernetes引入了Service资源。
Service资源可以聚合提供相同服务的多个Pod,并为它们提供一个统一的入口地址。这样,通过访问Service的入口地址,就可以访问到后台的Pod服务,而无需关心每个Pod的IP地址的变化。这使得服务的访问更加稳定和可靠,同时也提供了更好的可扩展性,因为可以轻松地增加或减少提供服务的Pod数量。

##### **4.5.1 ClusterIP**
```bash
# 等同于没有--type的
kubectl expose deployment my-dep --port=8000 --target-port=80 --type=ClusterIP
# 查看创建的service
kubectl get svc
# 访问
curl 10.96.226.54:8000 #ip为service的ip 能够看到负载均衡效果了
curl my-dep.default.svc:8000 # 必须在pod中访问!
# 部署一个tomat服务,在它的内部访问nginx
curl 10.96.226.54:8000
# Yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: my-dep
name: my-dep
spec:
ports:
- port: 8000
protocol: TCP
targetPort: 80
selector:
app: my-dep
type: ClusterIP
```
##### **4.5.2 NodePort**
暴露服务,集群外部可以访问,NodePort范围在 30000-32767 之间
```bash
# 暴露服务
kubectl expose deployment my-dep --port=8000 --target-port=80 --type=NodePort
#Yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: my-dep
name: my-dep
spec:
ports:
- port: 8000
nodeport: 30088 #指定绑定的node的端口
targetPort: 80
selector:
app: my-dep
type: NodePort
```
```bash
[root@k8s-master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1