keyfall / xuexibiji

3 stars 0 forks source link

K8S #22

Open keyfall opened 5 years ago

keyfall commented 5 years ago

image

keyfall commented 4 years ago

pod和pod控制器 pod: pod是k8s里能被运行的最小逻辑单元 1个pod里可以运行多个容器,共享UTS+NET+IPC名称空间

pod控制器: 是pod启动的一种模板,保证在k8s里启动的pod始终按照预期运行,比如我想有pod里的container始终启动着,那么只要有container停止了,pod就自动启动那个container 常用的container: Deployment 部署 DaemonSet 要求每个运算节点都启动一份 ReplicaSet 本身不直接对外,对外的是Deployment StatefulSet 管理有状态应用的 Job 管理任务的 Cronjob 管理定时周期计划任务

keyfall commented 4 years ago

name和namespace

name k8s内部,使用“资源”定义每一种逻辑概念(功能),所以每种资源都有自己名称 资源有api版本,类别,元数据,定义清单,状态等配置信息 名称通常定义在资源的元数据信息里

namespace 资源太多了,把资源分组,就是namespce(名称空间) k8s里默认存在的名称空间:default,kube-system,kube-public 查询k8s里特定资源要带上相应的名称空间

label和label选择器

label 比如一个资源可以打上错误的,未完成的,初始版本的,这种自定义标签 标签和资源是多对多 标签的组成:key=value

label选择器 过滤制定的标签,搜索标签 标签选择器有2个:基于等值关系(等于,不等于)和基于集合关系(属于,不属于,存在) 许多资源支持内嵌标签选择器字段: matchLabels matchExpressions

keyfall commented 4 years ago

Service和Ingress

service

k8s里,每个pod都会被分配一个单独的ip地址,可这个ip地址会随着pod的销毁而消失 service服务用来解决这个问题的核心概念 一个Service可以看做一组提供相同服务(一组相同类型)的pod的对外访问接口 Service作用于的pod,是通过标签选择器定义的

Ingress

Ingress是k8s集群里工作在OSI网络参考模型下,第7层的应用,对外暴露的接口 Service只能进行L4流量调度,表现形式是ip+port(ip:port) Ingress则可以调度不同业务域,不同url访问路径的业务流量(Ingress接收流量方向比Service更广) Ingress接收了一个流量,转到service,service转到pod

etcd服务:相当于一个数据库,存储节点信息的配置 image raft:读写信息,实时把数据和日志放到store进行持久化 wal:预写日志,对数据进行更改,先生成日志,进行保存一下(entry),并且会定时对这些修改进行备份(Snapshot),先生成小更改,到一个时间把小更改合起来生成一个大更改变成完整备份,主要是为了还原省时。

kube-apiserver服务 提供集群管理的REST API接口(包括鉴权,数据校验以及集群状态变更) 负责其他模块之间的数据交互,承担通信枢纽功能 资源配额控制的入口 提供完备的集群安全机制 相当于人的大脑,其他服务干什么事情,都需要给apiserver先提交请求

kube-controller-manager服务 由一系列控制器组成,通过apiserver监控整个集群的状态,并确保集群处于预期的工作状态

kube-scheduler服务 接收调度pod到适合的运算节点上 比如有个要开一堆pod的请求,apiserver找controller-manager按照定的模板去启动,然后controller-manager通过apiserver找到sheduler询问我这个定好的模板用哪个运算节点去运行 shcduler工作流程 预算策略:提供一个配置,通过apiserver找到etcd,得到节点的信息,看哪些node符合,提供到优选里面 优选策略:从预算策略提供的节点选择最优的

kube-kublet服务: 定时从某个地方获取节点上pod的期望状态,并调用对应的容器平台接口达到这个状态,比如说副本数量预期3个,变成2个了,kublet动一个 定时汇报当前节点的状态给apiserver,以供调度时使用 镜像和容器的清理工作

kube-proxy服务 k8s在每个节点上运行网络代理,service资源的载体 建立了pod网络和集群网络的关系(clusterip->podip) pod网络是kubelet提供的,proxy提供的是pod网络和集群网络的关系

k8s的三条网络 image

实验架构 image

keyfall commented 4 years ago

常见的k8s安装部署方式

keyfall commented 4 years ago

虚拟机安装

阿里云镜像找cenos7.6(其他版本我怕跟课程起冲突) vmware安装好进行克隆 image 克隆5个名称以ip替代,配置图片右边

eth,ens,lo是什么 image

修改hostname hostnamectl set-hostname hdss7-11.host.com 7-11是虚拟机名称后2位 注销重进

修改网卡配置 vi /etc/sysconfig/network-scripts/ifcfg-eth0 image 网关跟VMware的一样 其他的虚拟机,就ipaddr不同 如果ifcfg-eth0是空白的,说明没有这个网卡 ip addr看看除了lo还有什么,我这里是ens33,没有eth0 如果只有lo,关掉虚拟机,打开*.vmx文件,最后加入ethernet0.virtualDev = "e1000",重启(网上看的,没试过) 有ens33的话 image 重启systemctl restart network

keyfall commented 4 years ago

pod pod启动,必启动一个pause(网络栈),里面的container端口不能相同,可以通过pause进行交流,还有共享的挂载

管理器管理的pod ReplicationController用来确保容器应用的副本数始终保持在用户定义的副本数,就是如果有容易退出,会自动创建新的pod来替代,如果多了,就自动回收 不过现在不适用ReplicationController了,使用ReplicaSet替代

ReplicaSet与ReplicationController没有本质不同,只是多支持集合式selector,selector就是pod的标签,比如app-apache,version-1.0这类,ReplicaSet就是可以多选择这些标签,进行过滤选择pod

一般建议使用Deployment来自动管理ReplicaSet,因为ReplicaSet跟其他机制不兼容,比如rolling-update(滚动更新),但Deployment支持 rolling-update就是更新一个删除原来一个,首先Deployment创建出来后会创建一个ReplicaSet,然后ReplicaSet创建了3个pod,版本是v1,后来需要升级到v2,那么Deployment会再创建另一个RS,这个RS每创建一个v2的pod(估计是跑到第一个RS看到里面有一个v1的pod,那么就会创建一个v2的pod),那么前面的RS就会退出一个v1的pod,更新完后,第一个RS不会删除,会停用,为了后续可能v2出错了,想继续使用v1,进行undo,回滚,就是跟滚动更新反过来,创建一个v1,删除一个v2

HPA(horizontal Pod AutoScale),仅适用于Deployment和ReplicaSet,支持根据pod的CPU利用率扩容,需要定义HPA,然后HPA根据pod的资源利用率进行增加pod或者删除pod,默认最大10个pod,最小2个pod,默认如果pod的资源使用率高于80%,这太高容易坏掉,那么就会扩容,使得CPU利用率降下来

StatefulSet 为了解决有状态服务的问题(持续有状态,持久性,比如mysql,需要持续进行数据的操作),应用场景:

DaemonSet确保全部(或者一些(有的node添加了污点))node上运行一个且只有一个Pod副本当有node加入集群时,也会为他们新增一个pod,当有node从集群移除时,这些pod也会被回收,删除daemonSet将会删除它创建的所有pod 如果需要一个node上运行多个pod,那么可以建立多个DaemonSet或者把所有pod中需要的container提取出来放到一个pod中 使用daemonSet的一些典型用法:

Job负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个pod成功结束 比如封装好一个备份数据库功能的代码放到pod,再用job处理这个pod 优点是可以重复利用,第二是如果脚本意外退出了,那么job会重复进行操作,直到正常退出,第三是可以设置正常退出的次数。

Gron Job 管理基于时间的Job

keyfall commented 4 years ago

image php-fpm如果挂了,重新启动一个会改变名称等信息,那么squid找不到了,所以不能多对点,可以创建一个service,利用标签搜集到对应的php-fpm,那么squid只需要访问service的地址就行了

keyfall commented 4 years ago

网络通讯方式

k8s网络模型假定了所有pod都在一个可以直接连通的扁平的网络空间中,谷歌服务器中的GCE里面是现成的网络模型,在私有云里所以需要自己实现这个网络架设,将不同节点上的Docker容器之间的互相访问先打通,然后运行k8s,可以使用网络组件flannel进行架设

同一个pod内多个容器之间:pause容器网络栈,lo回环网卡 pod与Service之间的通讯:各节点的Iptables规则(最新版本使用LVS) 各pod之间通讯:overlay network

跨主机pod进行通讯 image

pod1至pod2:

ETCD对Flannel帮助:

keyfall commented 4 years ago

yum源更换为国内的阿里云yum源

# 备份
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
# 下载新的CentOS-Base.repo 到/etc/yum.repos.d/
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

或

curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
# 清理缓存并生成新的缓存
yum clean all
yum makecache

设置系统主机名以及 Host 文件的相互解析 hostnamectl set-hostname k8s-master01

安装依赖包 yum install -y conntrack ntpdate ntp ipvsadm ipset jq iptables curl sysstat libseccomp wget vim net-tools git

无jq软件包

wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -ivh epel-release-latest-7.noarch.rpm
yum repolist
yum install jq

设置防火墙为 Iptables 并设置空规则

systemctl stop firewalld && systemctl disable firewalld
yum -y install iptables-services && systemctl start iptables && systemctl enable iptables && iptables -F && service iptables save

关闭 SELINUX

swapoff -a && sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
setenforce 0 && sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config

调整内核参数,对于 K8S

cat > kubernetes.conf <<EOF
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
net.ipv4.tcp_tw_recycle=0
vm.swappiness=0 # 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它
vm.overcommit_memory=1 # 不检查物理内存是否够用
vm.panic_on_oom=0 # 开启 OOM
fs.inotify.max_user_instances=8192
fs.inotify.max_user_watches=1048576
fs.file-max=52706963
fs.nr_open=52706963
net.ipv6.conf.all.disable_ipv6=1
net.netfilter.nf_conntrack_max=2310720
EOF

cp kubernetes.conf /etc/sysctl.d/kubernetes.conf
sysctl -p /etc/sysctl.d/kubernetes.conf

调整系统时区

# 设置系统时区为 中国/上海
timedatectl set-timezone Asia/Shanghai
# 将当前的 UTC 时间写入硬件时钟
timedatectl set-local-rtc 0
# 重启依赖于系统时间的服务
systemctl restart rsyslog
systemctl restart crond

关闭系统不需要服务 systemctl stop postfix && systemctl disable postfix

设置 rsyslogd 和 systemd journald

mkdir /var/log/journal # 持久化保存日志的目录
mkdir /etc/systemd/journald.conf.d
cat > /etc/systemd/journald.conf.d/99-prophet.conf <<EOF
[Journal]
# 持久化保存到磁盘
Storage=persistent
# 压缩历史日志
Compress=yes
SyncIntervalSec=5m
RateLimitInterval=30s
RateLimitBurst=1000
# 最大占用空间 10G
SystemMaxUse=10G
# 单日志文件最大 200M
SystemMaxFileSize=200M
# 日志保存时间 2 周
MaxRetentionSec=2week
# 不将日志转发到 syslog
ForwardToSyslog=no
EOF

systemctl restart systemd-journald

升级系统内核为 4.44

rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
# 安装完成后检查 /boot/grub2/grub.cfg 中对应内核 menuentry 中是否包含 initrd16 配置,如果没有,再安装
一次!
yum --enablerepo=elrepo-kernel install -y kernel-lt
# 设置开机从新内核启动
grub2-set-default 0
下面是进行kernel更新成新的
7,卸载老版本kernel内核工具
rpm -qa|grep kernel|grep 3.10
rpm -qa|grep kernel|grep 3.10|xargs yum remove -y
备注:有一个正在运行的kernel3.10卸载不了,因为正在运行中,重启之后可卸载。

8,安装新版的工具包
yum --enablerepo=elrepo-kernel install -y kernel-tl-tools
检查:
rpm -qa|grep kernel

9,重启并检查版本
reboot
uname -a

kube-proxy开启ipvs的前置条件

modprobe br_netfilter

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 -- nf_conntrack_ipv4
EOF

chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules &&
lsmod | grep -e ip_vs -e nf_conntrack_ipv4

安装 Docker 软件

yum install -y yum-utils device-mapper-persistent-data lvm2

yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

yum update -y && yum install -y docker-ce

## 创建 /etc/docker 目录
mkdir /etc/docker
# 配置 daemon.
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
}
}
EOF

mkdir -p /etc/systemd/system/docker.service.d
# 重启docker服务
systemctl daemon-reload && systemctl restart docker && systemctl enable docker

安装 Kubeadm (主从配置)

cat <<EOF > /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

yum -y install kubeadm-1.15.1 kubectl-1.15.1 kubelet-1.15.1

systemctl enable kubelet.service

导入镜像,windows本地传到xshell无显示,下载下面的软件 yum install -y lrzsz

解压 tar -zxvf kubeadm-basic.images.tar.gz

新建loadsimages.sh(docker导入镜像)

#!/bin/bash

ls /root/kubeadm-basic.images > /tmp/image-list.txt

cd /root/kubeadm-basic.images

for i in $( cat /tmp/image-list.txt)
do
        docker load -i $i
done

rm -rf /tmp/image-list.txt

chmod a+x loadsimages.sh ./loadsimages.sh

这里可以把其他的节点进行copy 主节点 进行配置hosts vi /etc/hosts 最下面添加 ip hostname

10.4.7.11 k8s-master01
10.4.7.21 node10.4.7.21
10.4.7.22 node10.4.7.22

初始化master kubeadm config print init-defaults > kubeadm-config.yaml vi kubeadm-config.yaml 修改,podSubnet新加的

localAPIEndpoint:
    advertiseAddress: 192.168.66.10
kubernetesVersion: v1.15.1
networking:
  podSubnet: "10.244.0.0/16"
  serviceSubnet: 10.96.0.0/12
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
featureGates:
  SupportIPVSProxyMode: true
mode: ipvs

kubeadm init --config=kubeadm-config.yaml --experimental-upload-certs | tee kubeadm-init.log

部署flannel网络 wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml kubectl create -f kube-flannel.yml kubectl get pod -n kube-system 我的出现这个,kube-flannel-ds-amd64-pgfm5报错

NAME                                   READY   STATUS     RESTARTS   AGE
coredns-5c98db65d4-4kctj               0/1     Pending    0          10m
coredns-5c98db65d4-5bq2p               0/1     Pending    0          10m
etcd-k8s-master01                      1/1     Running    0          10m
kube-apiserver-k8s-master01            1/1     Running    0          9m50s
kube-controller-manager-k8s-master01   1/1     Running    0          10m
kube-flannel-ds-amd64-pgfm5            0/1     Init:0/1   0          47s
kube-proxy-fqwz5                       1/1     Running    0          10m
kube-scheduler-k8s-master01            1/1     Running    0          10m

进行检查 kubectl describe pod kube-flannel-ds-amd64-pgfm5 -n kube-system 看最后

Events:
  Type     Reason     Age                  From                   Message
  ----     ------     ----                 ----                   -------
  Normal   Scheduled  5m30s                default-scheduler      Successfully assigned kube-system/kube-flannel-ds-amd64-z27xg to k8s-master01
  Warning  Failed     61s (x3 over 4m12s)  kubelet, k8s-master01  Failed to pull image "quay-mirror.qiniu.com/coreos/flannel:v0.11.0-amd64": rpc error: code = Unknown desc = context canceled
  Warning  Failed     61s (x3 over 4m12s)  kubelet, k8s-master01  Error: ErrImagePull
  Normal   BackOff    27s (x5 over 4m12s)  kubelet, k8s-master01  Back-off pulling image "quay-mirror.qiniu.com/coreos/flannel:v0.11.0-amd64"
  Warning  Failed     27s (x5 over 4m12s)  kubelet, k8s-master01  Error: ImagePullBackOff
  Normal   Pulling    16s (x4 over 5m29s)  kubelet, k8s-master01  Pulling image "quay-mirror.qiniu.com/coreos/flannel:v0.11.0-amd64"

第一个warning显示failed,failed to pull image,所以是没有fail下来 直接daocker pull(如果pulling fs layer,是网络问题,换一下docker源,查查百度docker换源) docker pull easzlab/flannel:v0.11.0-amd64 修改镜像名称 docker tag easzlab/flannel:v0.11.0-amd64 quay.io/coreos/flannel:v0.11.0-amd64 这里apply的时候,下面会显示一堆configured,说明修改成功 kubectl apply -f kube-flannel.yml

podsecuritypolicy.policy/psp.flannel.unprivileged configured
clusterrole.rbac.authorization.k8s.io/flannel unchanged
clusterrolebinding.rbac.authorization.k8s.io/flannel unchanged
serviceaccount/flannel unchanged
configmap/kube-flannel-cfg unchanged
daemonset.apps/kube-flannel-ds-amd64 configured
daemonset.apps/kube-flannel-ds-arm64 configured
daemonset.apps/kube-flannel-ds-arm configured
daemonset.apps/kube-flannel-ds-ppc64le configured
daemonset.apps/kube-flannel-ds-s390x configured

再一次kubectl get pod -n kube-system 会显示正确

NAME                                   READY   STATUS    RESTARTS   AGE
coredns-5c98db65d4-4kctj               1/1     Running   0          51m
coredns-5c98db65d4-5bq2p               1/1     Running   0          51m
etcd-k8s-master01                      1/1     Running   1          51m
kube-apiserver-k8s-master01            1/1     Running   2          50m
kube-controller-manager-k8s-master01   1/1     Running   1          51m
kube-flannel-ds-amd64-sjrpr            1/1     Running   0          33s
kube-proxy-fqwz5                       1/1     Running   1          51m
kube-scheduler-k8s-master01            1/1     Running   1          50m

这时候进行其他节点的加入,在其他节点加入主节点初始化的时的代码 kubeadm join 192.168.56.11:6443 --token wbryr0.am1n476fgjsno6wa --discovery-token-ca-cert-hash sha256:7640582747efefe7c2d537655e428faa6275dbaff631de37822eb8fd4c054807

这里重点说一下: 主要针对没有科学上网,如果科学上网了,也不会出现这种问题 我在flannel总是会出现imagererror或者init:0/1这种,比如第一次通过kocker pull下载flannel的镜像,该名称(就是上面的方法)第二次进行了节点的加入,flannel还是会报错,由于flannel已经正确了,再更新也没用 看了kube-flannel.yml,里面很多的flannel下载地址(全是外网下载),我想意思就是,跟主节点上的不同,来普通节点了,flannel会去尝试新的下载,但是第二次他就没有找到pull的那个了,这时我从头重新进行了flannel的更新(从flannel没有create的时候进行flannel的pull改名),不过还是没用 我想起来kube-flannel.yml内容有下载地址,我可以直接修改所有下载地址,它就直接从容易下载的地方下载了,也不用管是否是主节点还是普通节点了,反正你都要从简单地址下载,结果还是报错了,第二天一早重新启动发现好了,这里觉得可能是需要重新启动一下,或者间隔10分钟,20分钟...(没试过不知道,反正我关电脑到开电脑9个小时,哈哈)

经历这件事我想通了,就根据这件事,我看了8,9个文章,大部分讲的都是pull flannel,然后改名,就看见一个说改kube-flannel.yml的,我想问问都没有进行节点添加么(还是说我着急了,pull完flannel之后需要等一会?),多尝试,需要从根源解决问题,就这件事根源就是kube-flannel.yml,其实最后能想到修改文件还是从一开始的懵逼,慢慢查,到知道为什么,从而突然想到的解决方法(这是是不是该看源码解决哈哈)。 科学上网是否重要?我觉得一般要看国外网站,那科学上网很重要,你不fq,等死你也上不去,再看这件事其实没科学上网也有收获,至少我知道了很多东西,比如docker镜像容器和k8s有联系,查询pod问题,删除pod...

vi全局替换方法:

:s/vivian/sky/ 替换当前行第一个 vivian 为 sky

:s/vivian/sky/g 替换当前行所有 vivian 为 sky

:n,$s/vivian/sky/ 替换第 n 行开始到最后一行中每一行的第一个 vivian 为 sky

:n,$s/vivian/sky/g 替换第 n 行开始到最后一行中每一行所有 vivian 为 sky

(n 为数字,若 n 为 .,表示从当前行开始到最后一行)

:%s/vivian/sky/(等同于 :g/vivian/s//sky/) 替换每一行的第一个 vivian 为 sky

:%s/vivian/sky/g(等同于 :g/vivian/s//sky/g) 替换每一行中所有 vivian 为 sky
#可以使用 # 作为分隔符,此时中间出现的 / 不会作为分隔符
:s#vivian/#sky/# 替换当前行第一个 vivian/ 为 sky/

题外话: 如果想卸载flannel kubectl delete -f kube-flannel.yml systemctl restart kubelet

由于先进行了节点加入,后来发现主节点错了,主节点进行了快照,退回到主节点中k8s not ready的时候,接着剩下操作,到了添加node的时候,需要在各节点进行k8s添加节点语句,报错

 [ERROR Port-10250]: Port 10250 is in use
[ERROR DirAvailable--etc-kubernetes-manifests]: /etc/kubernetes/manifests is not empty
[ERROR FileAvailable--etc-kubernetes-pki-ca.crt]: /etc/kubernetes/pki/ca.crt already exists
[ERROR FileAvailable--etc-kubernetes-kubelet.conf]: /etc/kubernetes/kubelet.conf already exists

这时候重启节点kubeadm,重新输入k8s生成的节点添加代码:

#重启节点
kubeadm reset
#master重新生成节点代码
kubeadm token create --print-join-command