摘自知乎:

k8s入门及实践

一、 k8s简介

K8S 是Kubernetes的全称,官方称其是:

Kubernetes is an open source system for managing containerized applications across multiple hosts. It provides basic mechanisms for deployment, maintenance, and scaling of applications.
用于自动部署、扩展和管理“容器化(containerized)应用程序”的开源系统

k8s是负责自当年规划运维管理多个docker程序的集群,比docker swarm门槛高,且功能强大

二、k8s组件

2.1 Master节点组件:

API Server: K8S 的请求入口服务, API Server 负责接收 K8S 所有请求(来自 UI 界面或者 CLI 命令行工具),然后,API Server 根据用户的具体请求,去通知其他组件干活

Scheduler:K8S 所有 Worker Node 的调度器,当用户要部署服务时,Scheduler 会选择最合适的 Worker Node(服务器)来部署

Controller Manager:K8S 所有 Worker Node 的监控器。Controller Manager 有很多具体的 Controller,在文章Components of Kubernetes Architecture中提到的有 Node Controller、Service Controller、Volume Controller 等。Controller 负责监控和调整在 Worker Node 上部署的服务的状态,比如用户要求 A 服务部署 2 个副本,那么当其中一个服务挂了的时候,Controller 会马上调整,让 Scheduler 再选择一个 Worker Node 重新部署服务。

etcd:K8S 的存储服务,etcd 存储了 K8S 的关键配置和用户配置,K8S 中仅 API Server 才具备读写权限,其他组件必须通过 API Server 的接口才能读写数据(见Kubernetes Works Like an Operating System)。

2.2 Work节点组件

Kubelet:Worker Node 的监视器,以及与 Master Node 的通讯器。Kubelet 是 Master Node 安插在 Worker Node 上的“眼线”,它会定期向 Worker Node 汇报自己 Node 上运行的服务的状态,并接受来自 Master Node 的指示采取调整措施。

Kube-Proxy:K8S 的网络代理。私以为称呼为 Network-Proxy 可能更适合?Kube-Proxy 负责 Node 在 K8S 的网络通讯、以及对外部网络流量的负载均衡。

Container Runtime:Worker Node 的运行环境。即安装了容器化所需的软件环境确保容器化程序能够跑起来,比如 Docker Engine。大白话就是帮忙装好了 Docker 运行环境。

Logging Layer:K8S 的监控状态收集器。私以为称呼为 Monitor 可能更合适?Logging Layer 负责采集 Node 上所有服务的 CPU、内存、磁盘、网络等监控项信息。

Add-Ons:K8S 管理运维 Worker Node 的插件组件。有些文章认为 Worker Node 只有三大组件,不包含 Add-On,但笔者认为 K8S 系统提供了 Add-On 机制,让用户可以扩展更多定制化功能,是很不错的亮点。

三、k8s重要概念

3.1 Pod

Pod是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元,可以被理解成一群可以共享网络、存储和计算资源的容器化服务的集合,同一个 Pod 之间的 Container 可以通过 localhost 互相访问,并且可以挂载 Pod 内所有的数据卷;但是不同的 Pod 之间的 Container 不能用 localhost 访问,也不能挂载其他 Pod 的数据卷

下面是一个Pod的yaml示例:

apiVersion: v1
kind: Pod
metadata:
  name: memory-demo
  namespace: mem-example
spec:
  containers:
  - name: memory-demo-ctr
    image: polinux/stress
    resources:
      limits:
        memory: "200Mi"
      requests:
        memory: "100Mi"
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
    volumeMounts:
    - name: redis-storage
      mountPath: /data/redis
  volumes:
  - name: redis-storage
    emptyDir: {}

apiVersion记录 K8S 的 API Server 版本,现在看到的都是v1,用户不用管。

kind记录该yaml 的对象,比如这是一份 Pod 的 yaml 配置文件,那么值内容就是Pod。

metadata记录了 Pod 自身的元数据,比如这个 Pod 的名字、这个 Pod 属于哪个 namespace(命名空间的概念,后文会详述,暂时理解为“同一个命名空间内的对象互相可见”)。

spec记录了 Pod 内部所有的资源的详细信息,看懂这个很重要:

containers记录了 Pod 内的容器信息,containers包括了:name容器名,image容器的镜像地址,resources容器需要的 CPU、内存、GPU 等资源,command容器的入口命令,args容器的入口参数,volumeMounts容器要挂载的 Pod 数据卷等。可以看到,上述这些信息都是启动容器的必要和必需的信息。

volumes记录了 Pod 内的数据卷信息,后文会详细介绍 Pod 的数据卷

3.2 Volume数据卷

volume 是 K8S 的对象,对应一个实体的数据卷;而 volumeMounts 只是 container 的挂载点,对应 container 的其中一个参数。但是,volumeMounts 依赖于 volume,只有当 Pod 内有 volume 资源的时候,该 Pod 内部的 container 才可能有 volumeMounts。

3.3 Container容器

一个 Pod 内可以有多个容器 container,在 Pod 中,容器也有分类

标准容器 Application Container
初始化容器 Init Container
边车容器 Sidecar Container
临时容器 Ephemeral Container

一般部署的还是以标准容器为主

3.4 Deployment和ReplicaSet(简称 RS)

Deployment 的作用是管理和控制 Pod 和 ReplicaSet,管控它们运行在用户期望的状态中。哎,打个形象的比喻,Deployment 就是包工头,主要负责监督底下的工人 Pod 干活,确保每时每刻有用户要求数量的 Pod 在工作。如果一旦发现某个工人 Pod 不行了,就赶紧新拉一个 Pod 过来替换它。

ReplicaSet 的作用就是管理和控制 Pod,管控他们好好干活。但是,ReplicaSet 受控于 Deployment。形象来说,ReplicaSet 就是总包工头手下的小包工头。

总结: 从 K8S 使用者角度来看,用户会直接操作 Deployment 部署服务,而当 Deployment 被部署的时候,K8S 会自动生成要求的 ReplicaSet 和 Pod. 用户只需要关心 Deployment 而不操心 ReplicaSet:

ReplicationController 确保在任何时候都有特定数量的 Pod 副本处于运行状态。 换句话说,ReplicationController 确保一个 Pod 或一组同类的 Pod 总是可用的,ReplicationController 是 ReplicaSet 的前身

3.5 Service 和 Ingress

Service官方定义:

将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法。
使用 Kubernetes,您无需修改应用程序即可使用不熟悉的服务发现机制。 Kubernetes 为 Pods 提供自己的 IP 地址,并为一组 Pod 提供相同的 DNS 名, 并且可以在它们之间进行负载均衡

K8S 中的服务(Service)并不是我们常说的“服务”的含义,而更像是网关层,是若干个 Pod 的流量入口、流量均衡器

Service 主要负责 K8S 集群内部的网络拓扑。那么集群外部怎么访问集群内部呢?这个时候就需要 Ingress 了

Ingress官方定义:

Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。
Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。

3.6 namespace 命名空间

namespace官方定义:

Kubernetes 支持多个虚拟集群,它们底层依赖于同一个物理集群。 这些虚拟集群被称为名字空间。

namespace 是为了把一个 K8S 集群划分为若干个资源不可共享的虚拟集群而诞生的,可以通过在 K8S 集群内创建 namespace 来分隔资源和对象

3.7 其他

四、k8s部署

k8s有多种部署方式,对新手来说,kubeadm部署会容易上手些,除非熟悉很多组件并且理解k8s整体框架和流程之后,使用二进制部署才会得心应手,以下为kubeadm部署笔记

4.1. 环境准备

系统环境

硬件最低要求系统版本docker版本roleip地址

Memory >= 2GB

CPU >= 双核

HardDisk >= 30GB

CentOS8.4.2105

(Linux version 4.18.0-348.xx

Red Hat 8.5.0-4)

20.10.12

k8s-master

192.168.100.129
k8s-node1192.168.100.130
k8s-node2192.168.100.131

推荐设置所有节点最好4GB内存以上,CPU4核,硬盘容量都至少设置100GB, 后续会不停更新

kubernetes组件

组件版本
kubeadm1.21.1-0
kubectl1.21.1-0
kubelet1.21.1-0

docker镜像

REPOSITORYTAG
registry.aliyuncs.com/google_containers/kube-apiserver    v1.21.1  
registry.aliyuncs.com/google_containers/kube-proxyv1.21.1
registry.aliyuncs.com/google_containers/kube-controller-managerv1.21.1
registry.aliyuncs.com/google_containers/kube-schedulerv1.21.1
registry.aliyuncs.com/google_containers/etcd3.4.13-0
registry.aliyuncs.com/google_containers/corednsv1.8.0
registry.aliyuncs.com/google_containers/pause3.4.1

4.2. 初始化虚拟机

在开始安装部署之前需要对所有的机器进行初始化环境,避免后续环境问题影响

4.2.1 关闭防火墙

在所有master节点和node节点都需要运行以下命令,只有2.5章节只需要在master上运行即可

systemctl stop firewalld
systemctl disable firewalld

4.2.2 关闭selinux

sed -i 's/enforcing/disabled/' /etc/selinux/config #永久
setenforce 0 # 临时

4.2.3 关闭swap

sed -ri 's/.*swap.*/#&/' /etc/fstab # 永久
swapoff -a # 临时

4.2.4 修改主机名称

hostnamectl set-hostname <hostname> # 示例
hostnamectl set-hostname k8s-master # 在master机器上输入
hostnamectl set-hostname k8s-node1  # 在node1机器上输入
hostnamectl set-hostname k8s-node2  # 在node2机器上输入

4.2.5 只在master中添加hosts

cat > /etc/hosts << EOF
192.168.100.129 k8s-master
192.168.100.130 k8s-node1
192.168.100.131 k8s-node2
EOF

4.2.6 桥接IPv4流量传递到iptables的链

cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system

4.2.7 时间同步

rpm -ivh http://mirrors.wlnmp.com/centos/wlnmp-release-centos.noarch.rpm # 添加wlnmp源
yum install wntp
ntpdate time.windows.com

# 如果发现当前区域不一致,可以通过以下命令修改区域
timedatectl                               # 查看当前区域
timedatectl list-timezone                 # 查看支持的时区
timedatectl set-timezone Asia/Shanghai    # 例如设置当前时区为亚洲/上海时区

4.3. 安装docker/kubeadmi/kubelet

Kubernetes默认CRI(容器运行时)为docker,因此先安装docker,所有节点都要安装并保持版本一致

4.3.1 安装docker

wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo  # 下载docker-ce源
yum install docker-ce -y                          # 安装docker-ce
systemctl enable docker && systemctl start docker # 开始docker并设置开机启动
docker --version                                  # 检查docker版本
systemctl status docker                           # 检查docker当前的状态

4.3.2 添加阿里云软件源

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=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

4.3.3 安装kubeadm, kubelet和kubectl

yum install -y kubelet-1.21.1 kubeadm-1.21.1 kubectl-1.21.1
systemctl enable kubelet

PS: 由于官网未开放同步方式, 可能会有索引gpg检查失败的情况, 这时请用 yum install -y --nogpgcheck kubelet kubeadm kubectl 安装

4.4 部署Kubernetes Master

4.4.1在 192.168.100.129(master)上执行

kubeadm init \
--apiserver-advertise-address=192.168.100.129 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version=v1.21.1 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16

# 由于默认拉取的镜像地址k8s.gcr.io国内无法访问,这里指定阿里云镜像仓库
# service-cidr和pod-network-cidr需要和其他机器IP不冲突皆可

拉取镜像的过程中可能会出现以下报错信息

error execution phase preflight: [preflight] Some fatal errors occurred:
        [ERROR ImagePull]: failed to pull image registry.aliyuncs.com/google_containers/coredns/coredns:v1.8.0: output: Error response from daemon: pull access denied for registry.aliyuncs.com/google_containers/coredns/coredns, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
, error: exit status 1
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher

由于coredns/coredns:v1.8.0镜像下载失败,可以手动下载该镜像然后修改tag名称, 并删除之前的TAG镜像

​docker pull coredns/coredns:1.8.0

docker tag coredns/coredns:1.8.0 registry.aliyuncs.com/google_containers/coredns/coredns:v1.8.0

docker rmi coredns/coredns:1.8.0

reset(可查看4.4.3 )之后再重新进行Init操作,发现可以成功

默认的token有效期为24小时,如果过期,该token就无法使用了,需要重新创建token,操作如下:

kubeadm token create --print-join-command

4.4.2 使用kubectl工具

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubectl get nodes      # 查看node节点
NAME         STATUS     ROLES                  AGE   VERSION
k8s-master   NotReady   control-plane,master   83m   v1.21.1

4.4.3 重置kubeadm

sudo kubeadm reset

有时会提示reset process does not clean XXXXX等等信息可以以下方法手动删除

删除net.d

rm -rf /etc/cni/net.d

重置iptables

iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X

sysctl net.bridge.bridge-nf-call-iptables=1

手动执行以下命令来清除对应的残余网卡信息:

sudo ip link del cni0

sudo ip link del flannel.1

删除 $HOME/.kube/config

rm -rf $HOME/.kube/config

4.5 加入Kubernetes Node

 4.5.1在192.168.100.130/131(Node)执行

kubeadm join 192.168.100.129:6443 --token kvsx31.dx0ir4wicki90wut \
        --discovery-token-ca-cert-hash sha256:2e731f87568256765fd0716f9d19c35a7777ea8c656f5559b177081328d7f16c

4.5.2 查看Master节点加入情况

kubectl get nodes      # 查看node节点
NAME         STATUS     ROLES                  AGE   VERSION
k8s-master   NotReady   control-plane,master   86m   v1.21.1
k8s-node1    NotReady   <none>                 17s   v1.21.1
k8s-node2    NotReady   <none>                 12s   v1.21.1

当前网络插件CNI未配置,所以当前状态都是NotReady

五、部署CNI网络插件

部署CNI网络插件在Master上完成

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

The connection to the server raw.githubusercontent.com was refused - did you specify the right host or port?

发现这个源是无法访问的,是因为无法解析这个域名,然后参考了这份老哥的博客,这个问题解决了 https://blog.csdn.net/weixin_38074756/article/details/109231865,感谢!

通过这个网站: http://ip.tool.chinaz.com/raw.githubusercontent.com 然后输入raw.githubusercontent.com

然后打开/etc/hosts文件将这个IP地址加入到hosts文件中 

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.100.129 k8s-master
192.168.100.130 k8s-node1
192.168.100.131 k8s-node2
185.199.111.133 raw.githubusercontent.com

 PS: 这个地址可能会一直变更,在部署之前确认下即可

重新运行apply命令

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/psp.flannel.unprivileged created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created

查看POD状态,这个时候所有节点的状态变更为Ready

kubectl get pods -n kube-system
NAME                                 READY   STATUS             RESTARTS   AGE
coredns-545d6fc579-62drv             0/1     ImagePullBackOff   0          123m
coredns-545d6fc579-bcrcg             0/1     ImagePullBackOff   0          123m
etcd-k8s-master                      1/1     Running            0          123m
kube-apiserver-k8s-master            1/1     Running            0          123m
kube-controller-manager-k8s-master   1/1     Running            0          123m
kube-flannel-ds-6nlcw                1/1     Running            0          9m57s
kube-flannel-ds-cl2n4                1/1     Running            0          9m57s
kube-flannel-ds-tt2xc                1/1     Running            0          9m57s
kube-proxy-4zv7h                     1/1     Running            0          123m
kube-proxy-75jvx                     1/1     Running            0          36m
kube-proxy-f8nm5                     1/1     Running            0          36m
kube-scheduler-k8s-master            1/1     Running            0          123m

此处发现coredns为ImagePullBackOff状态是因为其他节点上没有coredns的镜像,通过以下命令查看

kubectl get pods -A -o wide
NAMESPACE     NAME                                 READY   STATUS             RESTARTS   AGE     IP                NODE         NOMINATED NODE   READINESS GATES
default       nginx-6799fc88d8-mzgtx               1/1     Running            0          59m     10.244.2.2        k8s-node2    <none>           <none>
kube-system   coredns-545d6fc579-62drv             0/1     ImagePullBackOff   0          3h9m    10.244.1.2        k8s-node1    <none>           <none>
kube-system   coredns-545d6fc579-bcrcg             0/1     ImagePullBackOff   0          3h9m    10.244.1.3        k8s-node1    <none>           <none>

可以看出这个ImagePullOff的状态是在k8s-node1节点上,故在node1节点上安装coredns镜像即可,此处node2节点也同样操作

​docker pull coredns/coredns:1.8.0

docker tag coredns/coredns:1.8.0 registry.aliyuncs.com/google_containers/coredns/coredns:v1.8.0

docker rmi coredns/coredns:1.8.0

安装完成后再次检查pod状态,此时都是Running状态

kubectl get pods -n kube-system
NAME                                 READY   STATUS    RESTARTS   AGE
coredns-545d6fc579-62drv             1/1     Running   0          3h14m
coredns-545d6fc579-bcrcg             1/1     Running   0          3h14m
etcd-k8s-master                      1/1     Running   0          3h14m
kube-apiserver-k8s-master            1/1     Running   0          3h14m
kube-controller-manager-k8s-master   1/1     Running   0          3h14m
kube-flannel-ds-6nlcw                1/1     Running   0          81m
kube-flannel-ds-cl2n4                1/1     Running   0          81m
kube-flannel-ds-tt2xc                1/1     Running   0          81m
kube-proxy-4zv7h                     1/1     Running   0          3h14m
kube-proxy-75jvx                     1/1     Running   0          107m
kube-proxy-f8nm5                     1/1     Running   0          107m
kube-scheduler-k8s-master            1/1     Running   0          3h14m

查看Node状态

kubectl get nodes
NAME         STATUS   ROLES                  AGE     VERSION
k8s-master   Ready    control-plane,master   3h19m   v1.21.1
k8s-node1    Ready    <none>                 113m    v1.21.1
k8s-node2    Ready    <none>                 113m    v1.21.1

六、测试Kubernetes集群

6.1 在k8s中创建一个pod,验证是否正常运行:

kubectl create deployment nginx --image=nginx

# 在创建的过程中等待镜像拉取完成并且是Running的状态

# 通过以下命令查看

kubectl get pod
NAME                     READY   STATUS              RESTARTS   AGE
nginx-6799fc88d8-mzgtx   0/1     ErrImagePull        0          6s

当出现ErrImagePull状态的时候可以等一段时间

kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
nginx-6799fc88d8-mzgtx   1/1     Running   0          79m

目前发现本机拉取其他镜像失败,后续再看看如何

docker pull nginx
Using default tag: latest
Error response from daemon: toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit

放置一夜之后,又可以拉取了,可能是网络原因吧。。。。

6.2 设置对外的端口

kubectl expose deployment nginx --port=80 --type=NodePort
service/nginx exposed

# 对外暴露80端口,如果80端口被占用,使用其他端口

6.3 查看对外端口

kubectl get pod,svc
NAME                         READY   STATUS    RESTARTS   AGE
pod/nginx-6799fc88d8-mzgtx   1/1     Running   0          16h

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        18h
service/nginx        NodePort    10.96.33.37   <none>        80:32637/TCP   2m22s

# 服务此时对外端口为32637,可以用node节点通过这个端口来访问

6.4 Node访问此端口

http://192.168.100.131/132:32637

七、 卸载k8s相关组件

7.1 卸载kubelet\kubeadm\kubectl

yum remove -y kubelet kubeadm kubectl

7.2 停止k8s相关容器并移除docker相关镜像

docker stop $(docker container ls -a | grep google_containers | awk '{print $3}')

docker rm $(docker container ls -a | grep google_containers | awk '{print $3}')

docker rmi $(docker container ls -a | grep google_containers | awk '{print $3}')

7.3 删除本地残留文件

rm -rf ~/.kube/
rm -rf /etc/kubernetes/
rm -rf /etc/systemd/system/kubelet.service.d
rm -rf /etc/systemd/system/kubelet.service
rm -rf /usr/bin/kube*
rm -rf /etc/cni
rm -rf /opt/cni
rm -rf /var/lib/etcd
rm -rf /var/etcd

Logo

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

更多推荐