k8s的介绍

k8s的配置介绍

  1. 构建一套K8S云计算平台,至少2台服务器(硬件服务器),基于Linux操作系统,最好Linux内核3.8+以上,推荐使用3.10内核版本,对应Linux操作系统发行版:RHEL7.x、CentOS7.x、Ubuntu16.x;
  2. 构建K8S底层2台硬件服务器的配置:
  • CPU:1C
  • MEM:1G
  • DISK:40GB
  • NET:1000Mb+10Gb
  1. K8S云计算框架技术,C/S模式,Master节点和Node节点,1台Master节点,一台Node节点;
    Master节点称为控制节点,用于管理Node节点,对Node节点上资源进行调度和管理的;
    Node节点称为被控节点,用于创建Docker容器、虚拟机、管理容器、容器网络、镜像管理,主要用于提供云主机;
  2. 配置Master和Node节点网络连通,Node节点是用于Docker容器管理,启动Docker容器,为了实现宿主机跟其他宿主机上的Docker容器网络通信的话,引入Flannel软件,主要解决跨网络主机通信的
  3. NODE节点主要是用于资源分配、资源池,真正消耗资源的Node节点,而不是Master节点,可以添加节点、删除节点

Etcd

  • ETCD是分布式的K-V(KEY-VALUE)存储系统,称为配置文件代码保存中心,主要是用于存储K8S+Flannel网络相关的信息的,例如存储Flannel网段信息,K8S读取ETCD的K-V值,默认配置文件:/etc/etcd/etcd.conf

Flannel

  • 用来打通所有节点之间的网络,各个节点可以进行通信
  • Flannel网络读取ETCD配置中心的K-V,ETCD提前创建K-V信息,Flannel网络的配置段信息(IP段信息),在etcd配置中心创建K-V网段信息
# master节点上的操作
etcdctl  mk  /atomic.io/network/config '{"Network":"172.17.0.0/16"}'

k8s安装步骤

k8s平台必备条件(每台机器)

# 关闭自启动
systemctl disable firewalld
# 关闭防火墙
systemctl stop firewalld

# 关闭selinux
# 临时禁用selinux
setenforce 0
# 永久关闭 修改/etc/sysconfig/selinux文件设置
sed -i 's/SELINUX=permissive/SELINUX=disabled/g' /etc/sysconfig/selinux
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

# 禁用交换分区
swapoff -a
# 永久禁用,打开/etc/fstab注释掉swap那一行。
sed -i 's/.*swap.*/#&/' /etc/fstab

yum -y install ntp

# 同步时间
ntpdate pool.ntp.org
# 再启动服务
systemctl start ntpd 
systemctl enable ntpd

# 这个是第二种同步时间的方式(生产环境)
# 定时任务
# 每个3小时同步时间
0 */3 * * * ntpdate pool.ntp.org

# 重启一下crond
service crond restart

Kubernetes Master安装与配置

master服务
yum install kubernetes-master etcd flannel *rhsm* -y
etcd的配置
# etcd配置中心,可以单独部署在一台服务器上
# 配置etcd的配置
cd /etc/etcd
# 备份文件
cp etcd.conf etcd.conf.bak
# 查看不是#开头的配置
grep -v "^#" etcd.conf

# 数据目录
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
# localhost 替换为 etcd的服务ip
# 本地监听网卡和端口;
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
# 默认名字为default,可以随意去etcd1
ETCD_NAME="default"
# ETCD对外宣告访问地址;
ETCD_ADVERTISE_CLIENT_URLS="http://172.20.10.6:2379"

# vim里的替换
%s/localhost/172.20.10.6/g
sed -i "s/localhost/172.20.10.6/g" etcd.conf

# 通过不同的设置api 版本环境变量,支持的命令行不同
cat >> /etc/profile << EOF
export ETCDCTL_API=2
EOF

source /etc/profile
# 重启etcd的服务
service etcd restart
systemctl enable etcd

# etcd集群搭建
kubernetes的配置
cd /etc/kubernetes/

apiserver:用于用户、控制端去操作NODE节点的入口,API访问接口

# 配置apiserver
vim apiserver
KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"
# 配置etcd的服务ip
KUBE_ETCD_SERVERS="--etcd-servers=http://172.20.10.6:2379"
# default admission control policies
#KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"
# 不用账户和安全认证,去掉SecurityContextDeny,ServiceAccount
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,ResourceQuota"

# 配置config
vim config
# kube的本地ip
KUBE_MASTER="--master=http://172.20.10.6:8080"
# 如果为true,表示ui界面,在创建容器的时候,高级选项里面,可以以特权身份运行(root)
KUBE_ALLOW_PRIV="--allow-privileged=true"

# controller-manager和scheduler 不需要修改

# 开启服务
service kube-apiserver restart
service kube-controller-manager restart
service kube-scheduler restart

# 第二中开启服务
systemctl restart kube-apiserver
systemctl restart kube-controller-manager
systemctl restart kube-scheduler

# 开机启动
systemctl enable kube-apiserver
systemctl enable kube-controller-manager
systemctl enable kube-scheduler

# 查看服务 
ps -ef | grep -E "apiserver|manager|scheduler"

Kubernetes Node1安装与配置

node服务
yum install kubernetes-node docker flannel *rhsm* -y
kubernetes的配置
cd /etc/kubernetes/

# 3个配置文件的作用
config:客户端系统配置文件,指向Master端apiserver接口文件;
Kubelet:Node节点的agent客户端配置文件,监听Agent程序,同时指定master端口apisever,接受Master端控制,可以管理本地Docker引擎服务(下载镜像、启动容器、映射访问);
Proxy:代理配置文件,主要是用于后期服务均衡、服务访问使用的

# 配置config
vim config
# kube的master的ip
KUBE_MASTER="--master=http://172.20.10.6:8080"
# 如果为true,表示ui界面,在创建容器的时候,高级选项里面,可以以特权身份运行(root)
KUBE_ALLOW_PRIV="--allow-privileged=true"

# 配置kubelet
vim kubelet
# node1 本地ip
KUBELET_ADDRESS="--address=172.20.10.7"
KUBELET_HOSTNAME="--hostname-override=172.20.10.7"
# master ip
KUBELET_API_SERVER="--api-servers=http://172.20.10.6:8080"

# proxy 不需要修改

# 启动服务
service kube-proxy restart
service kubelet restart
service docker restart

systemctl restart kube-proxy
systemctl restart kubelet
systemctl restart docker

systemctl enable kube-proxy
systemctl enable kubelet
systemctl enable docker

Kubernetes flanneld 网络配置(每台)

# 作用
用来打通所有节点之间的网络,各个节点可以进行通信

cd /etc/sysconfig
# 配置flanneld
vim flanneld
# 配置etcd的ip
FLANNEL_ETCD_ENDPOINTS="http://172.20.10.6:2379"
# etcd里key的前缀,flannel根绝这个key的前缀,来获取网段信息,所以需要在etcd里创建该key前缀的信息
FLANNEL_ETCD_PREFIX="/atomic.io/network"

# 启动服务
service flanneld restart 

# 此时启动会启动不起来,需要去etcd的服务器里,配置相应的信息
# 添加网段的信息,以后容器里的ip都在这个范围
etcdctl mk /atomic.io/network/config '{"Network":"172.17.0.0/16"}'

# master node启动服务
service flanneld restart 
# 此时node 需要重启docker,保证docker和flannel在同一个网段
service docker restart 

# 第二种启动
systemctl restart flanneld
systemctl restart docker

# 开机启动
systemctl enable flanneld

Etcd测试

在Maste服务器,测试Etcd集群是否正常,

创建flannel网络配置:

vim /etc/profile
# 通过不同的设置api 版本环境变量,支持的命令行不同
export ETCDCTL_API=2
source /etc/profile
# 重启etcd的服务
service etcd restart

etcdctl member list
etcdctl cluster-health
# 获取网段的信息
etcdctl get /atomic.io/network/config
# 查看网络信息
etcdctl ls /atomic.io/network/subnets
# 删除,不操作
etcdctl rm /atomic.io/network/ --recursive

# 添加网段的信息
etcdctl mk /atomic.io/network/config '{"Network":"172.17.0.0/16"}'

ping通网络

# master
etcdctl ls /atomic.io/network/subnets
/atomic.io/network/subnets/172.17.20.0-24
/atomic.io/network/subnets/172.17.5.0-24
ping 172.17.20.0
ping 172.17.5.0

# node1
ping 172.17.20.0
ping 172.17.5.0

# 如果没有ping通,在master和node上执行
service flanneld restart;service docker restart;iptables -P FORWARD ACCEPT

查看结果

# 查看节点的信息
kubectl get nodes # 如果有结果了,就表示成功了
# 删除节点
kubectl delete nodes/172.20.10.8

# 查看日志
tail -fn 100 /var/log/messages

Kuberetes Dashboard UI实战

node服务器里的操作
# node服务器里的操作
# 下载两个镜像
pod-infrastructure
kubernetes-dashboard-amd64

docker pull docker.io/tianyebj/pod-infrastructure
docker pull siriuszg/kubernetes-dashboard-amd64:v1.6.3

# 修改镜像的名字,
docker tag $(docker images | grep pod-infrastructure | awk '{print $3}') registry.access.redhat.com/rhel7/pod-infrastructure
# 因为node节点中的/etc/kubernetes/kubelet 配置文件中指定的就是这个名字的镜像
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"

docker tag $(docker images | grep kubernetes-dashboard-amd64 | awk '{print $3}') bestwu/kubernetes-dashboard-amd64:v1.6.3
# 因为master节点中,创建dashboard-controller.yaml文件里指定了这个镜像的名字和版本
master服务的操作
mkdir -p /etc/dashboard

vim dashboard-controller.yaml
vim dashboard-service.yaml
dashboard-controller.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: kubernetes-dashboard
  namespace: kube-system
  labels:
    k8s-app: kubernetes-dashboard
    kubernetes.io/cluster-service: "true"
spec:
  selector:
    matchLabels:
      k8s-app: kubernetes-dashboard
  template:
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ''
        scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]'
    spec:
      containers:
      - name: kubernetes-dashboard
      # 注意镜像名和版本号
        image: bestwu/kubernetes-dashboard-amd64:v1.6.3
        resources:
          limits:
            cpu: 100m
            memory: 50Mi
          requests:
            cpu: 100m
            memory: 50Mi
        ports:
        - containerPort: 9090
        args:
        # 此处需要修改,master的ip
          - --apiserver-host=http://172.20.10.6:8080
        livenessProbe:
          httpGet:
            path: /
            port: 9090
          initialDelaySeconds: 30
          timeoutSeconds: 30
dashboard-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: kubernetes-dashboard
  namespace: kube-system
  labels:
    k8s-app: kubernetes-dashboard
    kubernetes.io/cluster-service: "true"
spec:
  selector:
    k8s-app: kubernetes-dashboard
  ports:
  - port: 80
    targetPort: 9090
启动
# master服务器里的操作
cd /etc/dashboard
# 启动
kubectl create -f dashboard-service.yaml
kubectl create -f dashboard-controller.yaml --validate=false

# 查看是否启动成功
kubectl get pods --all-namespaces

# 删除
kubectl delete -f dashboard-service.yaml
kubectl delete -f dashboard-controller.yaml

# 获取容器的ip和services的ip
kubectl get pods -o wide
kubectl get services -o wide

# 查看日志
tail -fn 100 /var/log/messages

# 访问
http://172.20.10.6:8080
# 访问ui界面
http://172.20.10.6:8080/ui

容器操作

通过UI界面操作
# 扩容10台nginx容器
点击overview->查看部署->点击nginx里的 查看/编辑->更改里面的配置replicas改为10

# 删除10台nginx容器
点击overview->查看部署->点击nginx里的 查看/编辑->更改里面的配置replicas改为1
然后再删除部署里的nginx->删除副本集的nginx->删除容器组的nginx
通过命令行
# master服务器
通过ui界面,首先先创建一台nginx容器
点击overview->查看部署->点击nginx里的 查看/编辑->点击复制
# 创建一台的时候这样操作
vim create_nginx.yaml
kubectl create -f create_nginx.yaml

Kubernetes平台组件概念

Kubernetes节点介绍

  • Kubernetes集群中主要存在两种类型的节点:master,minion(node)节点
  • Minion节点为运行Docker容器的节点,负责和节点上运行的
  • Docker进行交互,并且提供了代理功能

Kubernetes master的介绍

  • Kubelect Master:Master节点负责对外提供一些列管理集群的API接口,并且通过和Minion(node)节点交互来实现对集群的操作管理
  • apiserver:用户和kubernetes集群交互的入口,封装了核心对象的增删改查操作,提供了RESTFul风格的API接口,通过etcd来实现持久化并维护对象的一致性
  • scheduler:负责集群资源的调度和管理,例如当有pod(相当于一个盒子,里面装了很多容器,容器组)异常退出需要重新分配机器时,scheduler通过一定的调度算法从而找到最合适的节点
  • controller-manager:主要用于保证replication(副本) controller定义的复制数量和实际运行的pod数量一致,另外还保证了从service到pod的映射关系总是最新的

Kubernetes node的介绍

  • kubelet:运行在minion(node)节点,负责和节点上的Docker交互,例如启停容器,监控运行状态等
  • proxy:运行运行在minion(node)节点,负责为pod提供代理功能,会定期从etcd获取service信息,并根据service信息通过修改iptables来实现流量转发(最初的版本是直接通过程序提供转发功能,效率较低),将流量转发到要访问的pod所在的节点上去

Etcd

  • etcd是一个分布式一致性k-v存储系统数据库,可用于服务注册发现与共享配置存储数据库,用来存储kubernetes的信息的,etcd组件作为一个高可用,强一致性的服务发现存储仓库,渐渐为开发人员所关注。在云计算时代,如何让服务快速透明地接入到计算集群中,如何让共享配置信息快速被集群中的所有机器发现,更为重要的是,如何构建这样一套高可用,安全,易于部署以及响应快速的服务集群,etcd的诞生就是为解决该问题

etcd的操作:

etcdctl help
# 查看
etcdctl ls /
# 创建目录
etcdctl mkdir /user
# 设置值
etcdctl set /user/name zs
# 获取值
etcdctl get /user/name

# 删除值
etcdctl rm /user/name
# 删除文件夹
etcdctl rmdir /user

Flannel

  • Flannel是CoreOs团队针对Kubernetes设计的ige覆盖网络(Overlay Network)工具,Flannel目的就是为集群中的所有节点重新规划IP地址的使用规则,从而使得不同节点上的容器能够获得同一个内容且不重复的IP地址,并让属于不同节点上的容器能够直接通过内容IP通信

POD

  • 容器集合,调度部署的基本单位

例如:有两台node机器,需要部署3台centos和3台nginx

# 部署的结果
node1:有2台centos容器,2台nginx容器,这个就表示,该node1里有两个pod,一个pod负责2台centos容器,一个pod负责2台nginx的容器
node2:有2台centos容器,1台nginx容器,这个就表示,该node2里有两个pod,一个pod负责1台centos容器,一个负责1台nginx的容器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SR0K3QC8-1583832328404)(./images/pod.png)]

service

  • pod访问代理抽象,作用,就是不关心ip的变化,因为重启的时候,容器的ip会发生变化
  • Service是kubernetes最核心的概念,通过创建service,可以为一组具有相同功能的POD应用提供统一的访问入口,并且将请求进行负载分发到后端的各个容器应用上
  • 在kubernetes中,在受到RC(副本)调控的时候,pod副本是变化的,对于虚拟ip也是变化的,比如发生迁移或者伸缩的时候,这对于pod访问者来说是不可接受的(ip发生变化,很难根据ip去访问项目)
  • Kubernetes分配给service的固定ip是要给虚拟ip,并不是一个真实的ip,在外部是无法寻址的,在真实的系统实现上,kubernetes是通过kube-proxy组件来实现的虚拟ip路由及转发,所以在之前集群部署的环节上,我们在每个node上均部署了proxy这个组件,从而实现了kubernetes层级的虚拟转发网络

内部服务:

  • 会生成一个cluster ip,在宿主机上通过访问cluster ip加映射的端口号,就可以访问,外部需要访问的话,需要在通过nginx转发
例如,创建2台nginx的内部服务,端口映射30080-80,生成一个cluster ip 10.254.10.54,在master或node机上访问,http://10.254.10.54:30080,即可访问到内部的nginx
外部需要访问的话,可以通过nginx转发

外部服务

  • 会生成一个cluster ip,指定的映射端口和随机的端口,外部需要访问的话,node-ip:随机端口
例如,创建2台nginx的外部服务,端口映射30081-80,生成一个cluster ip 10.254.127.27,以及一个随机端口号30546,在master或node机上访问,http://10.254.127.27:30081,即可访问到内部的nginx;
外部需要访问的话,也可以直接任意node-ip:随机端口,可以利用nginx的负载均衡,也可以利用nginx转发
外部访问service

Kubernetes提供了NodePort,LoadBalancer,lngress三种方式:

  • NodePort,原理是Kubernetes会在每一个Node上暴露出一个端口:NodePort,外部网络可以通过(任一Node)[NodeIp]:[NodePort](随机端口)访问到后端的service
  • LoadBalancer,在NodePort基础上,Kubernetes可以请求底层云平台创建一个负载均衡器,将每个Node作为后端,进行服务分发,该模式需要底层平台(例如GCE)支持

例如NodePort(外部服务),nginx的配置:

upstream k8s_nginx {
		# max_fails表示尝试连接的次数,fail_timeout表示超市的时间单位为秒
        server 172.20.10.7:30546 weight=1 max_fails=2 fail_timeout=15;
        server 172.20.10.8:30546 weight=1 max_fails=2 fail_timeout=15;
    }

server {
    listen  80;
    server_name  _;
    charset  utf-8;
    client_max_body_size  1024M;
    fastcgi_read_timeout  600s;

    location  / {
    	proxy_set_header Host $host;
    	proxy_pass  http://k8s_nginx;
    }
}

replication controller(RC)

  • 副本集,pod的复制抽象,副本集有多少,同一时刻就存在多少数量的容器

k8s工作原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AGrlF3Mo-1583832328407)(./images/k8s.png)]

各服务的作用

  • apiserver 用户通过kubectl命令向apiserver发送创建service的命令,apiserver接受到请求以后将数据存储到etcd中
  • kube-proxy kubernetes的每个节点中都有一个叫做kube-proxy的进程,这个进程负责感知service,pod的变化,并将变化的信息写入到本地的iptables中
  • iptables 使用NAT等技术将virtual ip(虚拟ip)的流量转至endpoint中

查看网络规则

# 虚拟ip对应到那个容器
iptables -t nat -L -n --line-numbers | more
# 查看路由规则
route -n

k8s升级

更新

# 将服务sh-nginx-v1部署应用的镜像修改为 最新的镜像名称:nginx:v1
# -n:命名控件 sh-nginx-v1 服务名称,把该服务更新为最新的nginx
kubectl -n default set image deployments/sh-nginx-v1 sh-nginx-v1=nginx:v1

回滚

# 把服务sh-nginx-v1回滚到上一个版本
kubectl -n default rollout undo deployments/sh-nginx-v1

# 查看回滚的状态
kubectl -n default rollout status deployments/sh-nginx-v1

查看版本

# 查看所有版本信息
kubectl rollout history deploy/sh-nginx-v1 
# 查看版本的详细信息
kubectl rollout history deploy/sh-nginx-v1 --revision=2

# 回滚到指定的版本
kubectl -n default rollout status deployments/sh-nginx-v1 --to-revision=3

k8s开启多个centos

下载centos镜像

# 下载镜像,带ssh的
docker pull docker.io/lemonbar/centos6-ssh

# 该镜像的名字
docker tag docker.io/lemonbar/centos6-ssh 172.20.10.6:5000/centos6

# push到docker私有仓库
docker push 172.20.10.6:5000/centos6

在ui界面上创建centos

# 容器镜像,会去本地仓库拉取
172.20.10.6:5000/centos6

# 然后查看镜像的ip,登录进去
ssh root@ip  # 初始密码为123456

# 查看登录密码(master)
docker history centos6  # master
docker history 172.20.10.6:5000/centos6 # node

# 拷贝模板,显示的好看一些
cp /etc/skel/.bash* /root/
su

traceroute(查看ip访问)

yum install traceroute -y

traceroute # 查看help
# 可以查看本地是怎么去一步步访问到别人的IP的
traceroute www.baidu.com

 1  gateway (172.20.10.1)  3.051 ms  2.907 ms  3.936 ms
 2  * * *
 3  172.16.2.53 (172.16.2.53)  62.444 ms  62.304 ms  62.147 ms
 4  * * *
 5  111.47.195.57 (111.47.195.57)  42.056 ms  41.945 ms  41.841 ms
 6  211.137.61.49 (211.137.61.49)  48.203 ms  38.259 ms  38.157 ms
 7  221.183.39.209 (221.183.39.209)  42.172 ms * 221.183.39.213 (221.183.39.213)  52.230 ms
# 本地访问到www.baidu.com,是先走网关172.20.10.1,然后转到172.16.2.53,然后...

问题

k8s v1.5.2 中 service的cluster ip无法访问的问题