中文文档https://kubernetes.io/zh-cn/docs/home/

1.机器规划

IPhostnameRole组件
10.224.76.114k8s-masterMasterdocker、cri-dockerd、kubelet、kubeadm 、 kubectl、Flannel、etcd等镜像
10.224.76.115k8s-node1Nodedocker、cri-dockerd、kubelet、kubeadm 、 kubectl
10.224.76.116k8s-node2Nodedocker、cri-dockerd、kubelet、kubeadm 、 kubectl

1.设置hostname

每台机器都执行,设置对应的hostname

# 在相应的机器上执行
#master
hostnamectl set-hostname k8s-master
#node1
hostnamectl set-hostname k8s-node1
#node2
hostnamectl set-hostname k8s-node2

2.编辑/etc/hosts

每台机器都执行

cat >> /etc/hosts << EOF
10.224.76.114 k8s-master
10.224.76.115 k8s-node1
10.224.76.116 k8s-node2
EOF

3.安装ntpdate并同步时间

yum -y install ntpdate
ntpdate ntp1.aliyun.com
systemctl start ntpdate
sustemctl enable ntpdate
systemctl status ntpdate

4.关闭防火墙

systemctl stop firewalld.service 
systemctl disable firewalld.service

5.关闭selinux

sed -i 's/enforcing/disabled/' /etc/selinux/config  # 永久关闭

2.安装 Docker

1.安装Docker

CentOS安装Docker以及常用命令

换成国内docker仓库

cat <<EOF > /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn" // 国内镜像
  ],
  "insecure-registries": ["192.168.1.10:5000"],  // 内部仓库
  "exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
# 重启docker
systemctl restart docker
# 查看docker信息
docker info

2.安装容器运行时cri-dockerd

参考: https://github.com/Mirantis/cri-dockerd 可以从release版本中直接下载rpm包安装比较简单

# 下载
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.1/cri-dockerd-0.3.1-3.el7.x86_64.rpm
# 安装
rpm -ivh cri-dockerd-0.3.1-3.el7.x86_64.rpm

配置cri-docker使用国内镜像

vim /usr/lib/systemd/system/cri-docker.service

修改配置如下:

ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9

启动服务

systemctl daemon-reload && systemctl start cri-docker && systemctl enable cri-docker

查看服务状态

systemctl status cri-docker

3.安装K8S

1.禁用swap【重要】

因为Kubernetes 不支持在节点上启用交换空间。

检查交换空间状态

# 查不到记录 就是没有开启
sudo swapon --show

禁用交换空间

sudo swapoff -a

永久禁用交换空间(可选):

sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
#确保输出为空或所有 swap 条目都被注释掉。
cat /etc/fstab | grep swap

2.安装Kubernetes相关软件

1.添加 Kubernetes 软件仓库,修改Kubernetes源

修改为阿里云源

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

2.更新缓存

yum clean all
yum -y makecache
# 查看可安装版本
yum list kubelet --showduplicates | sort -r 

3.安装 kubelet、kubeadm 和 kubectl

这里安装的版本是1.26.6。
自 1.24 版起,Dockershim 已从 Kubernetes 项目中移除。即默认不支持docker了。

  • kubelet:是运行在每个 Kubernetes 节点上的代理程序,负责管理节点上的容器和 Pod。kubelet 接收来自 Master 节点的指令,根据这些指令来创建、启动、停止、监控 Pod,并与容器运行时(如 Docker)进行交互,确保 Pod 在节点上按预期运行。

  • kubeadm:用于在 Kubernetes 环境中启动和管理集群的工具。它能够帮助你进行集群的初始化、添加新节点、重置集群状态等操作,简化了集群的部署和管理过程。kubeadm 通常用于搭建 Kubernetes 集群的第一步,它可以配置集群的网络、安装核心组件等。

  • kubectl:是 Kubernetes 的命令行工具,用于与 Kubernetes 集群进行交互。通过 kubectl,你可以管理集群中的各种资源,如 Pod、Service、Deployment 等。它支持对集群进行部署、扩容、升级、维护等操作,是 Kubernetes 集群管理的主要工具之一。

# 没安装过的直接跳过卸载步骤
kubeadm reset
# 卸载老版本
sudo systemctl stop kubelet
sudo yum remove kubelet kubeadm kubectl
# 清理相关文件和目录(可选)
sudo rm -rf /etc/kubernetes /var/lib/kubelet /var/lib/kube-proxy /var/lib/kubernetes /var/run/kubernetes /etc/systemd/system/kubelet.service.d
# 清理 Docker 中的容器和镜像(可选)
sudo docker rm -f $(sudo docker ps -aq)
sudo docker rmi -f $(sudo docker images -aq)

# 安装指定版本
yum install -y kubelet-1.26.6-0 kubeadm-1.26.6-0 kubectl-1.26.6-0
# 检查版本信息
kubelet --version
kubectl version --output=json
kubeadm version
# 启动
sudo systemctl start kubelet
# 开机自启
systemctl enable kubelet
systemctl status kubelet
# 如果kubelet 异常 执行下列命令查看日志 我经常碰到异常,但是过一会儿自己好了。。。
journalctl -xeu kubelet

3.master节点拉取k8s镜像

仅在master节点执行

kubeadm config images pull --kubernetes-version=v1.26.6 --image-repository registry.aliyuncs.com/google_containers  --cri-socket=unix:///var/run/cri-dockerd.sock
#查看镜像
docker images 

registry.aliyuncs.com/google_containers/kube-apiserver            v1.26.6          
registry.aliyuncs.com/google_containers/kube-proxy                v1.26.6          
registry.aliyuncs.com/google_containers/kube-scheduler            v1.26.6          
registry.aliyuncs.com/google_containers/kube-controller-manager   v1.26.6               
registry.aliyuncs.com/google_containers/kube-proxy                v1.26.4                 
registry.aliyuncs.com/google_containers/etcd                      3.5.6-0          
registry.aliyuncs.com/google_containers/pause                     3.9              
registry.aliyuncs.com/google_containers/coredns                   v1.9.3      

4.初始化Kubernetes Master节点

仅在master节点执行

#注:10.224.76.114是本机IP地址
kubeadm init --kubernetes-version=1.26.6 --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=10.224.76.114 --ignore-preflight-errors=all --image-repository=registry.aliyuncs.com/google_containers --cri-socket=unix:///var/run/cri-dockerd.sock
  • –kubernetes-version:指定Kubernetes的版本。
  • –pod-network-cidr: 指定pod网络的IP地址,它的值取决于你选择哪个网络,比如Flannel网络,因此值需要指定为10.244.0.0/16,因为Flannel网络相对于其他网络要简单一些,对于刚开始搭建Kubernetes集群比较友好,需要的配置较少,功能也较为完善。
  • –apiserver-advertise-address: 指定master节点发布的IP地址,如果不指定,则会自动检测网络接口,通常是内网IP。
  • –ignore-preflight-errors:检查错误将显示为检查的警告列表。值为all会忽略所有检查中的错误。
  • –image-repository:选择一个Container Registry从中拉取控制平面镜像(默认为k8s.gcr.io,这个Container Registry拉取镜像特别慢,会导致超时,换成阿里云的Container Registry)。
  • –-cri-socket:指定cri-dockerd接口,如果是containerd则使用unix:///run/containerd/containerd.sock

初始化成功日志如下:

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/

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

kubeadm join 10.224.76.114:6443 --token bca3ta.ivxr8huu3f560645 \
        --discovery-token-ca-cert-hash sha256:dc07fce82b93428828b7b70e5f6c024ef64c43fc4d0c50b84b95d1e5deeb16b3

配置

# 要使非 root 用户可以运行 kubectl,请运行以下命令
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 如果你是root 用户,则可以运行:
export KUBECONFIG=/etc/kubernetes/admin.conf
# 如果想重新初始化,可执行kubeadm reset

# 直接给它放到环境变量中,以免关闭服务器后重新启动
vim /etc/profile
#放到最后面
export KUBECONFIG=/etc/kubernetes/admin.conf
# 保存并关闭文件,然后重新加载 /etc/profile 文件以使更改生效:
source /etc/profile

# 一条命令搞定
echo 'export KUBECONFIG=/etc/kubernetes/admin.conf' | sudo tee -a /etc/profile && source /etc/profile

5.在集群中加入node节点(仅在node节点执行)

如果是单节点版本就跳过这个步骤。

复制上面的join token

kubeadm join 10.224.76.114:6443 --token bca3ta.ivxr8huu3f560645 \
        --discovery-token-ca-cert-hash sha256:dc07fce82b93428828b7b70e5f6c024ef64c43fc4d0c50b84b95d1e5deeb16b3  --cri-socket=unix:///var/run/cri-dockerd.sock

注意加上 --cri-socket=unix:///var/run/cri-dockerd.sock

如果找不到加入的token,则在master节点生成节点加入的token

kubeadm token create --print-join-command

可能问题
1./etc/kubernetes/kubelet.conf 已存在

# 说明之前加入过 删除该文件以重新初始化
sudo rm -f /etc/kubernetes/kubelet.conf

2.Container runtime 未运行

sudo systemctl status containerd
sudo systemctl start containerd
# 如果启动失败,检查日志:
sudo journalctl -u containerd

3./etc/kubernetes/pki/ca.crt已存在

# 通常发生在多次尝试加入或重新初始化时未清理旧的 Kubernetes 配置文件
# 清理之前的 Kubernetes 配置和证书文件
sudo kubeadm reset -f
# 或者
kubeadm reset  --cri-socket=unix:///var/run/cri-dockerd.sock 

6.安装网络插件

通常使用 Calico 或 Flannel 作为网络插件。这里以 Flannel 为例,可以通过以下命令安装 Flannel 网络插件:

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

获取flannel pod状态:

kubectl get pod -n kube-system

最后,我们看下node的状态:显示为Ready就表示已经OK啦

kubectl get node
kubectl get node -o wide
kubectl cluster-info
kubectl get pod --all-namespaces
# 用 kubectl describe 来查看这个节点(Node)对象的详细信息、状态和事件(Event)
kubectl describe node master
# 通过 kubectl get 重新检查 Pod 的状态:
kubectl get pods -n kube-system
# 部署过程中任何环节有问题都可以查看日志 
journalctl -l -u kubelet

7.单机版解除限制

默认k8s的master节点是不能跑pod的业务,需要执行以下命令解除限制。

单机版才需要搞这个。

kubectl get nodes
#查看污点
kubectl describe node k8s-master|grep -i taints
#去除污点
kubectl taint node k8s-master1 node-role.kubernetes.io/control-plane:NoSchedule-
#再次查看污点
kubectl describe node k8s-master|grep -i taints

4.部署nginx

1.创建命名空间

# 创建命名空间
kubectl create namespace laker

2.创建Deployment+Service

kubectl apply -f nginx-k8s.yaml

nginx-k8s.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: laker
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25.5
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service          # Service 的名称,用于唯一标识该服务
  namespace: laker             # 所属的命名空间,决定该服务的作用域
spec:
  ports:                       # 定义服务暴露的端口配置
    - nodePort: 30080          # 节点上的端口,每个节点都将暴露这个端口范围(30000-32767),可以通过该端口访问服务
      port: 80                 # ClusterIP(集群内部)监听的服务端口
      protocol: TCP            # 使用的协议类型,默认是 TCP
      targetPort: 80           # Pod 内部的容器端口,服务请求会转发到该端口
  selector:                    # 标签选择器,用于将该服务与 Pod 关联
    app: nginx                 # 匹配拥有 `app=nginx` 标签的 Pod
  type: NodePort               # Service 类型,表示该服务通过每个节点的固定端口暴露

3.查看nginx pod service

kubectl -n laker get pod,svc -o wide

4.验证nginx

浏览器访问:http://10.224.76.114:30080

5.常用命令

# 查看 pod  -n指定namespace 否则是 default namespace
kubectl -n laker get pod -o wide
# 查看集群信息
kubectl cluster-info
# 查看所有节点
kubectl get nodes
# 查看指定命名空间下的所有资源
kubectl get all -n <namespace> 
# 进入 pod 
kubectl -n laker exec -it pod名称 bash
# 编辑 pod
kubectl -n laker edit deployment nginx-deployment
# 删除 pod 
kubectl -n laker delete deployment nginx-deployment
# 编辑 Service
kubectl -n laker edit service nginx-service
# 删除 Service
kubectl -n laker delete service nginx-service
# 查看 pod、Service
kubectl -n 命名空间 get pod,svc -o wide
# 进入容器内部
kubectl -n laker exec -it <podname> -- /bin/bash
kubectl -n laker exec -it <podname> -- bash
kubectl -n laker exec -it <podname> -- sh
# 列出环境变量
kubectl -n laker exec "$POD_NAME" -- env
# 重启 deployment
kubectl rollout restart -n laker deployment nginx-deployment
# 删除 service
kubectl delete -n laker service nginx-service
# 版本
kubectl version --short

高级

部署应用

创建应用实例后,Kubernetes Deployment 控制器会持续监视这些实例。 如果托管实例的节点关闭或被删除,则 Deployment 控制器会将该实例替换为集群中另一个节点上的实例。 这提供了一种自我修复机制来解决机器故障维护问题。

公开暴露应用

Service

Kubernetes Pod 是转瞬即逝的。 当一个工作节点挂掉后, 在节点上运行的 Pod 也会消亡。 ReplicaSet会自动地通过创建新的 Pod 驱动集群回到目标状态,以保证应用正常运行。 换一个例子,考虑一个具有 3 个副本的用作图像处理的后端程序。 这些副本是可替换的。前端系统不应该关心后端副本,即使某个 Pod 丢失或被重新创建。 此外,Kubernetes 集群中的每个 Pod 都有一个唯一的 IP 地址,即使是在同一个 Node 上的 Pod 也是如此, 因此需要一种方法来自动协调 Pod 之间的变化,以便应用保持运行

Kubernetes Service是一种抽象概念,它定义了 Pod 的逻辑集和访问 Pod 的协议。 Service 使从属 Pod 之间的松耦合成为可能。 和所有 Kubernetes 对象清单一样, Service 用 YAML 或者 JSON 来定义。 Service 下的一组 Pod 通常由一个 标签选择算符 来标记 (请参阅下面的说明为什么你可能想要一个 spec 中不包含 selector 的 Service)。

尽管每个 Pod 都有一个唯一的 IP 地址,但是如果没有 Service,这些 IP 不会被公开到集群外部。 Service 允许你的应用接收流量。 通过设置 Service 的 spec 中的 type,你可以用不同的方式公开 Service:

  • ClusterIP(默认)- 在集群的内部 IP 上公开 Service。这种类型使得 Service 只能从集群内访问。

  • NodePort - 使用 NAT 在集群中每个选定 Node 的相同端口上公开 Service 。使用<NodeIP>:<NodePort> 从集群外部访问 Service。是 ClusterIP 的超集。

    在每个节点上暴露相同的端口,流量直接通过节点端口访问,可以访问master和node节点相同端口都可以通

  • LoadBalancer - 在当前云中创建一个外部负载均衡器(如果支持的话),并为 Service 分配一个固定的外部IP。是 NodePort 的超集。

  • ExternalName - 将 Service 映射到 externalName 字段的内容(例如 foo.bar.example.com),通过返回带有该名称的 CNAME 记录实现。不设置任何类型的代理。这种类型需要 kube-dns 的 v1.7 或更高版本,或者 CoreDNS 的 0.8 或更高版本。

Ingress

Ingress 提供了对外部流量的统一访问控制,可以管理多个服务的访问规则,比如路由到不同的服务、路径重写等。
适用于需要更灵活访问控制和路径路由的场景。
安装并配置 Ingress 控制器
Ingress 依赖于 Ingress 控制器(Ingress Controller),它是一个负责处理 Ingress 资源的组件。不同的云平台和环境中有不同的 Ingress 控制器(如 Nginx Ingress Controller、Traefik、Istio等)。这里以 Nginx Ingress Controller 为例。

版本对应关系 https://github.com/kubernetes/ingress-nginx

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.4/deploy/static/provider/cloud/deploy.yaml
# 验证部署是否成功
kubectl get pods -n ingress-nginx
# 如果报错 查看日志
kubectl logs ingress-nginx-controller-55f8b958c4-d7dnm -n ingress-nginx

如果提示错误为:

7 main.go:64] port 80 is already in use. Please check the flag --http-port
且你用命令查询并没有占用的话,请更改其中的 allowPrivilegeEscalation为 true
在这里插入图片描述

# 卸载
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.4/deploy/static/provider/cloud/deploy.yaml
# 路由外部流量到 Kubernetes 集群内的 Service。
apiVersion: networking.k8s.io/v1 # 指定 API 版本,Ingress 资源使用 networking.k8s.io/v1。
kind: Ingress # 声明资源类型为 Ingress。
metadata:
  name: nginx-ingress # 定义 Ingress 的名称为 nginx-ingress。
  namespace: laker # 定义 Ingress 所属的命名空间为 laker。
  labels:
    name: laker-ingress # 标签,用于标识该 Ingress 对象,可用于选择或组织资源。

spec:
  rules:
  - host: laker.demo.com # 定义规则,指定的域名 laker.demo.com 会路由到指定的 Service。
    http:
      paths:
      - pathType: Prefix # 指定路径匹配类型为前缀匹配(路径以给定值开头)。
        path: "/" # 所有以 "/" 开头的请求将路由到指定的 backend。
        backend:
          service:
            name: nginx-service # 指定目标 Service 的名称为 nginx-service。
            port: 
              number: 80 # 指定目标 Service 的端口号为 80。

配置 DNS 或本地 Hosts 文件

<EXTERNAL-IP> laker.demo.com

访问 laker.demo.com

扩缩容应用

扩缩是通过改变 Deployment 中的副本数量来实现的。

kubectl -n laker get deployments
kubectl -n laker scale deployment nginx-deployment --replicas=2
# 检查 Pod 的数量是否发生变化
kubectl -n laker get pods -o wide

滚动更新

滚动更新 允许通过使用新的实例逐步更新 Pod 实例,实现零停机的 Deployment 更新。 新的 Pod 将被调度到具有可用资源的节点上。

要更新应用程序的镜像版本到 v2,请使用 set image 子命令,后面给出 Deployment 名称和新的镜像版本:

kubectl set image deployment/nginx-deployment nginx=nginx:1.25.5 -n laker

要回滚 Deployment 到上一个工作的版本,请使用 rollout undo 子命令:

kubectl rollout undo deployment/nginx-deployment -n laker

问题

问题1.工作节点name显示localhost,ROLES显示为none

忘记设置机器的hostname了

[root@k8s-master ~]# kubectl get nodes
NAME          STATUS   ROLES           AGE     VERSION
k8s-master1   Ready    control-plane   5d23h   v1.26.6
localhost     Ready    <none>          10m     v1.26.6

解决

# master上 删除节点
kubectl delete node localhost
# master上 查看是否删除完毕
kubectl get nodes
# node上 
kubeadm reset  --cri-socket=unix:///var/run/cri-dockerd.sock 
# master上 
kubeadm token create --print-join-command
# node上 
kubeadm join 10.224.76.114:6443 --token npopgd.ydlfidy8kt9n2p3d --discovery-token-ca-cert-hash sha256:dc07fce82b93428828b7b70e5f6c024ef64c43fc4d0c50b84b95d1e5deeb16b3 --cri-socket=unix:///var/run/cri-dockerd.sock
# master上 验证
kubectl get nodes

# 为节点分配角色标签,你可以使用以下命令
kubectl label node k8s-node2 node-role.kubernetes.io/worker=

问题2. pod、service间如何访问

解决

通过 DNS:Service 会自动分配一个 DNS 名称,格式为 <service-name>.<namespace>.svc.cluster.local。Pod 可以通过 Service 的 DNS 名称来访问 Service。

curl http://nginx-service.laker.svc.cluster.local:80
curl http://nginx-service.laker
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐