k8s_day01_02
1、k8s 组件/程序 简单介绍
kube-apiserver:

apiserver 运行的程序 叫kube-apiserver,go语言研发出来的组件。 kube-apiserver 其实就是把etcd 存储系统的kv schema 存储方案 封装为固定格式 , 可以理解为kube-apiserver就是一个数据库,定义了数据库的存储格式 ,etcd想象成是个mysql, 数据库中每个表字段的定义格式我把它叫做数据方案 ,也就是schema 。而apiserver就像是在etcd 上加了封装 。只支持特定格式数据(schema)的存储。

而这些格式都是 kv 或者文档格式组成的

kube-scheduler

​ scheduler 执行程序文件名称

kube-controller-manager
 controller-manager  执行程序文件名称:管理应用程序的扩缩容、滚动更新等功能的一个组件,为啥叫manager 呢?因为包含了很多controller:  Router controller(管理路由的)   Deployment controller (管理应用部署的)   volume  controller  (管理存储卷的)     node  controller  (管理节点的)    replicaset  controller  (管理复制集的)    volume  controller  (管理存储卷的)   等等 将近4~50 个,这些独立的应用程序打包成一个程序就是 controller-manager 

也可以在apiserver 中注册自研的控制器 叫operator

kubelet

​ 每个node 节点都有一个kubelet 程序, 与apiserver 之前通过https 协议 进行交互 ,且是双向认证 客户端服务端都要证书

​ kubelet 监听 apiserver 上自己注册 监听那些重要的数据的变动, 一旦和自己有关,在节点本地就要完成一些操作,实现特定的功能。比如 容器的增删改查 网络功能的增删改查等等,kubelet 为了支持更多不同功能的实现,它里面含有3个不同的容器接口

​ CNI: 容器网络接口 为容器提共网络插件功能

​ CSI: 容器存储接口 。容器数据应该拥有脱离容器自己生命周期机制,因此需要使用外部的存储空间 或者内嵌的存荐插件 来对接外部 各种存储设备 ,从而为容器提供存储卷

​ CRI: 容器运行时接口 : 意味着 kubelet 不仅能支持docker 如过是 CRI-O 也行 ,可以灵活对接不同的容器引擎

Pod:

​ 在k8s 上 容器不是直接拿来运行的 ,而是又附加了一层外壳 或者称为 又被重新抽象成了一个概念,这个概念就叫做Pod . 在k8s 上要运行容器 ,必须把这容器定义为一个叫pod 的组件。 一个 Pod 内可以允许有多个容器存在。 Pod 是 k8s 最小的调度单元,所以对于每次调度,一个pod 内的多个容器必须运行在同一台机器上。和docker 网络模型中 联盟容器一样: 不仅共享网络名称空间 、还共享主机名称空间、用来进程间通信、传递信号的IPC名称空间

kube-proxy:

是node 之上的另外一组件,管理service的。 在k8s 上 ,还需要为每一组实例,比如我运行了多个应用,还要为这些实例定义村软件的负载均衡器。客户端的请求先到负载均衡器 再到容器上

在k8s 上要运行一个应用,必须依赖下面2个组件

Controller

​ 要运行容器,必须先运行Pod, 但是呢 ,我们也不会直接创建Pod ,而是先创建控制器对象,可以理解为控制器是一个schema ,可以想象成一张空表,有固定字段, 创建一个控制器对象就是 你以控制的语法格式向这表中插入一行数据,这个数据就是存在apiserver 上。但是这个 创建的控制器对象 会被控制器的守护进程 根据数据项的定义 ,来确定它定义的结果发生了。

因为k8s 是一种声明式配置

比如 打车 去万达

直接告诉 司机 我要去万达。 这是 声明式配置 ,只关注结果 ,而不是在乎 过程 ,管它司机是否绕路、车技是否娴熟呢

告诉司机 先左拐 ,后右拐 ,再停车 。。。。 这是 过程式配置

 	比如 你告诉 Controller 运行3个 nginx  容器,它肯定就会运行3个nginx 容器  ,至于它是怎么运行起来的,你不用管,如果跑不起来,它就会报错,会告诉你,这就是声明式配置。
	 创建个Controller  就是说,添加个数据项,这个数据项就是 定以了nginx xx版本的镜像,创建几个nginx 完了。
 	 至于它是怎么运行起来的,你不用管,Controller 会联系apiserver把数据项 存进去,一旦POd 创建完之后,kube-scheduler会发现Pod 还没有被调度,会调度一下,接着被度节点的kubelet 会发现其中一个pod 调度给自己了,kubelet会到api-server 把相关数据拉下来,根据数据项的定义 ,到docker-registry  把镜像加载,启动一个容器,但它运行为Pod 格式

Service

​ 所以跑容器是靠Controller 来定义的。如果这时 创建3个pod ,其中一个宕了,Controller 会告诉apiserver 让它再创建一个pod,但是这个pod 的地址可能会变, 因此 这3个pod 提供的服务 会因为这种原因被客户端找不到,因此需要一个负载均衡器 ,也就是service.

问题:配置负载均衡器,需要添加 rs地址,如何知道新添加的Pod地址呢,这时候就需要利用到 标签

​ 这个 service 可以叫做 service 资源 ,也叫service 对象。你可以 把service 也看成是一张表, 创建一个service 对象 ,就是向service 表中插入一条数据。

​ pod、controller 、service 都可以称为对象

注意: 在k8s 中,所有的对象 都可以拥有一个叫标签的东西 叫 label. 同一组的pod 会有相同的标签定义。

​ service在添加pod 时会使用 一中 叫 标签选择器的东西: 叫 label selector ,可以理解为就是一个标签匹配条件。 只要满足标签匹配条件的pod 都是我调度的对象, 在匹配到label 后 ,会自动探测出pod的ip. 每个pod的IP是什么 ,apiserver 里面有。

更重要的是,service 同样会监视apiserver 上和满足自己标签匹配器的pod有关的变动 ,比如这个pod 被人删除少了一个,那么apiserver 上就少一个,那么 label selector 匹配到pod 也就少一个,service 监视到了这个变动,所以后端ip 少一个。

一切都以apiserver 为中心 建立交互关系 , 可以把apiserver 人为是 大家组件的communication BUS 通信总线

同理controller ,也是通过 标签选择器来管理这些pod, 而不是ip

2、k8s 如何引入外部流量?

容器间跨宿主机通信 的2种模型: 隧道(overlay)、路由(underlay)、 这2种模型天然对外部就有边界。只能用于集群内部通信,无法引入集群外部流量,因为节点是边界。 无论是 overlay、 还是underlay ,他们用的网段和物理机都不是一个网段,他们都是私有网络。要引入外部流量,只能靠节点跳一下,转一下,比如

​ 1、让容器共享宿主机的网络名称空间,监听宿主机的某个端口 就行。 但是这是很危险的,如果容器有bug,或者在容器内干坏事 就完了。 2、做Dnat, 把外部的地址转成内部的,转给service

3、部署kubeadm

简单部署的方式第一种:kubeadm

部署条件

  1. 分布式软件 ,必须要求时区一致
  2. 关闭防火墙【为了初学简单点】
  3. 关闭swap , 除非你强制忽略这个错误
  4. 确保所有节点 id 唯一
systemctl stop firewalld

yum install  chrony

systemctl restart docker 

swapoff  -a
/etc/fstab  注释 swap

cat  <<EOF > /etc/docker/daemon.json
{
"exec-opts":["native.cgroupdriver=systemd"]
}
EOF
 
echo  "net.bridge.bridge-nf-call-iptables = 1   > /etc/sysctl.d/k8s.conf &&sysctl -p     /etc/sysctl.d/k8s.conf
 
cat  <<EOF >>  /etc/hosts
192.168.2.1  master01.magedu.com   master01  kubeapi.magedu.com 
EOF


systemctl enable docker  kubeadm

master 需要安装的组件

​ kube-apiserver , kube-controller-manager ,kube-scheduler ,etcd

worker 组件

​ kubelet, kube-proxy,docker

因为官方提供的组件kubeadm 把 控制平面的组件以pod 方式部署的,所以master 节点也要部署 kubelet、kube-proxy、docker ,只不过他们是静态Pod。

三个节点是必须部署kubeadm、kubelet 的呢,但是kubelet无法部署为Pod 的形式,因为容器无法实现系统级管理,容器和系统的文件系统是隔离的

​ kubeadm 的工具作用是 让master 成为master ,让node 加入到k集群中

kubelet 和docker 会以系统的守护进程运行

注意 客户端工具kubectl ,哪台机器需要,哪台机器安装,但是以rpm 方式部署的话,kubectl 是被依赖的,所以不用管

172。16.0.1  master01.magedu.com  master01

172.16.0.2    node01.magedu.com  node01

kube-init 只能在master 控制节点上执行

kube-init 的作用 是拉起一个控制平面,传参有两种方式一种是直接传多个参参数,另一种是参数是传配置文件 -config string

[root@N1 ~]# kubeadm  init --help

会执行的步骤

  1. preflight 预检查

  2. certs: 创建证书。

  3. kubeconfig : 生成kubeconfig 配置文件。 kubelet 要想连接apiserver 会加载配置文件kubeconfig提供自己的证书,并且验证对方的证书。双向验证

  4. kubelet-start 启动kubelet 程序

  5. control-plane 启动控制平面组件

  6. etcd

  7. upload-config 上传配置

  8. upload-certs 上传证书 【作用是为了以后的高可用控制平面所设计的】

  9. bootstrap-token 引导令牌,以方便其他节点加入

  10. addon 安装附件

    • coredns 服务发现的组件
    • kubeproxy

    控制平面所有组件的镜像文件 都位于gcr.io 的这样镜像仓库上, 可以理解为谷歌的容器运行时

init 初始化参数

  • –image-repository string Choose a container registry to pull control plane images from (default “k8s.gcr.io”)
    设置镜像拉取控制平面节点镜像仓库仓库地址,默认谷歌

    可以设置为 阿里云

    --image-repository string   registry.aliyuncs.com/google_containers
    

    这里参数要么都用等于,要么都不用

  • –kubernetes-version string Choose a specific Kubernetes version for the control plane. (default “stable-1”)

    ​ 设置k8s版本, 要选择和kubeadm 版本一致

    [root@N1 ~]# rpm  -q  kubeadm
    kubeadm-1.19.4-0.x86_64
    [root@N1 ~]# 
    
    --kubernetes-version 1.19.4
    
  • –control-plane-endpoint string Specify a stable IP address or DNS name for the control plane.

    ​ 告诉客户端 连接控制节点用什么域名或IP 【kubeapi的地址】 ,非必须参数,可写可不写

    --control-plane-endpoint  kubeapi.magedu.com
    
  • –apiserver-advertise-address string The IP address the API Server will advertise it’s listening on. If not set the default network interface will be used.

    ​ 设置apiserver 的地址 ,不写的默认会自动探测

  • –apiserver-bind-port int32 Port for the API Server to bind to. (default 6443)

    ​ 默认6443

  • –pod-network-cidr string Specify range of IP addresses for the pod network. If set, the control plane will automatically allocate CIDRs for every node.

    ​ 设置准备把那个网段地址分给给pod 用,不同的网络插件的默认网段不一样,例如flanel 用10.244.0.0/16,如果不指定也没关系,以后安装网络插件时可以再改

    --pod-network-cidr 10.244.0.0/16
    

    kubeadm config image 可以先把镜像拉下来 ,测试仓库可管用

    image-20211124180828717
  • –token-ttl duration The duration before the token is automatically deleted (e.g. 1s, 2m, 3h). If set to ‘0’, the token will never expire (default 24h0m0s)

    设置token 过期的时间,默认24小时

    节点加入到ks 集群中所需的令牌。过期的好处就是为了避免令牌外泄,随意让其他节点加入

    这是控制平面的
    
    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 kubeapi.magedu.com:6443 --token sjh4s0.lsj3y7swfjpf9d2g \
        --discovery-token-ca-cert-hash sha256:f65cce015ac254b3e7c3a0cac59ac031079d9c31ffac12f31940a57d15c30764 \
        --control-plane 
    
    这是工作节点的
    
    Then you can join any number of worker nodes by running the following on each as root:
    
    kubeadm join kubeapi.magedu.com:6443 --token sjh4s0.lsj3y7swfjpf9d2g \
        --discovery-token-ca-cert-hash sha256:f65cce015ac254b3e7c3a0cac59ac031079d9c31ffac12f31940a57d15c30764 
    
    

合起来就是这

 kubeadm  init  --image-repository   registry.aliyuncs.com/google_containers  --kubernetes-version 1.19.4 --control-plane-endpoint  kubeapi.magedu.com  --apiserver-advertise-address 192.168.2.1   --pod-network-cidr 10.244.0.0/16

屏幕出现 Your Kubernetes control-plane has initialized successfully! 控制平面已经拉起来了

发现镜像已经下来了

[root@master01 ~]# docker image  ls
REPOSITORY                                                        TAG        IMAGE ID       CREATED         SIZE
registry.aliyuncs.com/google_containers/kube-proxy                v1.19.4    635b36f4d89f   12 months ago   118MB
registry.aliyuncs.com/google_containers/kube-controller-manager   v1.19.4    4830ab618586   12 months ago   111MB
registry.aliyuncs.com/google_containers/kube-apiserver            v1.19.4    b15c6247777d   12 months ago   119MB
registry.aliyuncs.com/google_containers/kube-scheduler            v1.19.4    14cd22f7abe7   12 months ago   45.7MB
registry.aliyuncs.com/google_containers/etcd                      3.4.13-0   0369cf4303ff   15 months ago   253MB
registry.aliyuncs.com/google_containers/coredns                   1.7.0      bfe3a36ebd25   17 months ago   45.2MB
registry.aliyuncs.com/google_containers/pause                     3.2        80d28bedfe5d   21 months ago   683kB
[root@master01 ~]# 

发现需要以普通用户创建配置文件

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

为了方便就用root 做了,生成用普通用户熬

没有创建配置文件前
[root@master01 ~]# kubectl  get nodes
The connection to the server localhost:8080 was refused - did you specify the right host or port?
[root@master01 ~]# 
创建之后
[root@master01 ~]# mkdir  .kube
[root@master01 ~]# cp /etc/kubernetes/admin.conf   .kube/config
[root@master01 ~]# kubectl  get nodes
NAME       STATUS     ROLES    AGE   VERSION
master01   NotReady   master   13m   v1.19.4

发现是 status是notReady ,这是因为网络插件还没有部署

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/

这里使用网络插件选择flannel ,因为简单。到github 上下载 flannel 的yaml

https://github.com/flannel-io/flannel

image-20211124190925442
[root@master01 ~]# wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml


[root@master01 ~]# kubectl  apply -f kube-flannel.yml
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
[root@master01 ~]# 

查看集群cs 状态 cs: componet 注意的是这个命令在1.19+ 版本已经废弃

[root@master01 ~]# kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME                 STATUS      MESSAGE                                                                                       ERROR
scheduler            Unhealthy   Get "http://127.0.0.1:10251/healthz": dial tcp 127.0.0.1:10251: connect: connection refused   
controller-manager   Unhealthy   Get "http://127.0.0.1:10252/healthz": dial tcp 127.0.0.1:10252: connect: connection refused   
etcd-0               Healthy     {"health":"true"}                                                                             
[root@master01 ~]# 

查看pod 运行状态

[root@master01 ~]# kubectl  get pods -n kube-system
NAME                               READY   STATUS    RESTARTS   AGE
coredns-6d56c8448f-jl7rf           1/1     Running   0          36m
coredns-6d56c8448f-pnw2n           1/1     Running   0          36m
etcd-master01                      1/1     Running   0          36m
kube-apiserver-master01            1/1     Running   0          36m
kube-controller-manager-master01   1/1     Running   0          36m
kube-flannel-ds-584qq              1/1     Running   0          4m47s
kube-proxy-p6wqt                   1/1     Running   0          36m
kube-scheduler-master01            1/1     Running   0          36m

等会发现 master 节点状态已经ready

[root@master01 ~]# kubectl  get nodes
NAME       STATUS   ROLES    AGE   VERSION
master01   Ready    master   39m   v1.19.4

客户端命令kubectl 的用法

kubectl 就是为了联系到apiserver上 进行资源增删查改的命令

[root@master01 ~]# kubectl  --help

 Usage:
  kubectl [flags] [options]

查看帮助,子命令有以下几个分类

Basic Commands : 基础命令

Deploy Commands 部署命令

Cluster Management Commands 集群管理命令

Troubleshooting and Debugging Commands: 排障命令

Advanced Commands:高级命令

Settings Commands:

Settings Commands:

(并且子命令还可以以插件的方式提供)

kubectl get --help Display one or many resources 列出一个或者多个资源

Examples:

# List all pods in ps output format
kubectl get pods

这里的资源名称 pods 是不是复数都行

kubectl api-resources 列出所有的资源类型

[root@master01 pki]# kubectl api-resources
NAME                              SHORTNAMES   APIVERSION                        NAMESPACED   KIND
bindings                                       v1                                true         Binding
componentstatuses                 cs           v1                                false        ComponentStatus
configmaps                        cm           v1                                true         ConfigMap
endpoints                         ep           v1                                true         Endpoints
events                            ev           v1                                true         Event
limitranges                       limits       v1                                true         LimitRange
namespaces                        ns           v1                                false        Namespace
nodes                             no           v1                                false        Node

NAME是资源名称, SHORTNAMES 是简称。pod 可以写成po ,当然你写成pod 也没问题,以下3种形式都行

[root@master01 pki]# kubectl  get pod  -n  kube-system
[root@master01 pki]# kubectl  get pods  -n  kube-system
[root@master01 pki]# kubectl  get po   -n  kube-system
# List all pods in ps output format with more information (such as node name)
kubectl get pods -o wide

资源空间: namespace 定义

用处 :用于不同项目 或者生产测试的 环境隔离。 默认是名称空间是 kube-system 和 mysql 数据库的默认数据库mysql 一样,用于保存系统关键数据 如 控制平面pod 和其他关键pod

[root@master01 pki]# kubectl  get ns
NAME              STATUS   AGE
default           Active   21h
kube-node-lease   Active   21h
kube-public       Active   21h
kube-system       Active   21h
[root@master01 pki]# kubectl  get pods   -n default
No resources found in default namespace.
[root@master01 pki]# kubectl  get pods   -n   kube-node-lease
No resources found in kube-node-lease namespace.
[root@master01 pki]# kubectl  get pods   -n    kube-public
No resources found in kube-public namespace.

默认的 自带ns中只有 kube-system 有数据

重置kubeadm 控制节点生产环境一定不要随便乱搞,因为重置并不是100%可以做好没问题的

当然 ,除了主节点,其他node 节点也可以删除。 不过除了reset 外,还要在主节点上把node 资源给删除了

[root@master01 ~]# kubeadm reset
[root@master01 ~]# rm -f  ~/.kube/config 
[root@master01 ~]# rm -rf  /etc/kubernetes

添加node

[root@N3 ~]# kubeadm join kubeapi.magedu.com:6443 --token sjh4s0.lsj3y7swfjpf9d2g     --discovery-token-ca-cert-hash sha256:f65cce015ac254b3e7c3a0cac59ac031079d9c31ffac12f31940a57d15c30764 


[root@master01 ~]# kubectl   get  nodes
NAME       STATUS   ROLES    AGE     VERSION
master01   Ready    master   54m     v1.19.4
node01     Ready    <none>   2m1s    v1.19.4
node02     Ready    <none>   9m33s   v1.19.4

运行一个容器

通过纯命令的方式,deployment 专门编排无状态应用的

[root@master01 ~]# kubectl  create deployment   demoapp   --image ='ikubernetes/demoapp:v1.0' --dry-run=client
deployment.apps/demoapp created (dry run)
[root@master01 ~]# 

如果只是测试以下可以用 --dry-run

[root@master01 ~]# kubectl  create deployment    --help

--dry-run='none': Must be "none", "server", or "client". If client strategy, only print the object that would be sent, without sending it. If server strategy, submit server-side request without persisting the resource.

真正运行去了 --dry-run 就行

[root@master01 ~]# kubectl create deployment demoapp   --image='ikubernetes/demoapp:v1.0' 
deployment.apps/demoapp created
[root@master01 ~]# 

[root@master01 ~]# kubectl create deployment demoapp  --image='ikubernetes/demoapp:v1.0'
deployment.apps/demoapp created
[root@master01 ~]# kubectl get pods  -o wide
NAME                       READY   STATUS    RESTARTS   AGE    IP           NODE     NOMINATED NODE   READINESS GATES
demoapp-5f7d8f9847-c5bbk   1/1     Running   0          104s   10.244.4.5   node02   <none>           <none>

默认新创建的pod 在 default 的 ns 中

[root@master01 ~]# kubectl   get  po  -n   default
NAME                       READY   STATUS    RESTARTS   AGE
demoapp-5f7d8f9847-c5bbk   1/1     Running   0          7m37s

访问新跑的的容器

[root@master01 ~]# curl  10.244.4.5
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: demoapp-5f7d8f9847-c5bbk, ServerIP: 10.244.4.5!

控制平台上配置pods个数

kubectl scale deployment demoapp --replicas=3 (deployment要和前面运行容器的名字一样)

验证 ks 会守护pod ,发现新生成的pod ip 会变

image-20211125022237286

为了可以固定访问,创建service. 软负载, 注意这里service 名称 必须和之前的deploy 保持一致

[root@master01 ~]# kubectl delete service   demonapp  
service "demonapp" deleted
[root@master01 ~]# kubectl create service  clusterip demoapp  --tcp=80:80
service/demoapp created
[root@master01 ~]# kubectl  get service
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
demoapp      ClusterIP   10.107.176.51   <none>        80/TCP    11s
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   124m
[root@master01 ~]# 


验证效果 curl clusterip

[root@master01 ~]# curl  10.107.176.51
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: demoapp-5f7d8f9847-c5bbk, ServerIP: 10.244.4.5!
[root@master01 ~]# curl  10.107.176.51
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: demoapp-5f7d8f9847-ggk9j, ServerIP: 10.244.4.6!
[root@master01 ~]# curl  10.107.176.51
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: demoapp-5f7d8f9847-wxz7l, ServerIP: 10.244.5.6!
##删除Pod
kubectl delete pods +pod名称
kubectl delete pods demoapp-59bb775755-5sn4q

#创建service
kubectl create service clusterip +容器名称 +协议及端口
kubectl create service clusterip demoapp --tcp=80:80

#查看创建的service
kubectl get service
Logo

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

更多推荐