k8s 笔记

一. 解决pod间依赖性

1.手动的采用不同顺序启动不同pod

2.定义restart policy(默认为alway,我们可以定义当某条件不满足时就一直重启,当满足条件是才启动容器)

3.如果对于强依赖的场景我们可以定义initContainers,必须满足条件才启动相应pod

4.stateFulset 

二. 如果某个SVC被重启了,那么相应的依赖他的对应app也要重启,或则会导致服务不可用,

以下场景:

我们有两个app,nginx和php-fpm,两个pod独立部署,nginx依赖php-fpm的svc,如果我们将php-fpm以及他的svc删除重建,虽然nginx使用的是php-fpm的services name,但是依然会导致nginx无法连接php-fpm的svc,我们必须重启nginx的pod才能工作正常

解决方案:我们在定义某个app时将svc与app分成不同的yml文件,如果配置变更了只需重启app,向外提供服务的svc不变,不会影响到依赖此SVC的其他pod

三. 一个pod中可以运行多个container,多个container共享相同的网络名称空间,但是文件系统是相互隔离的,如果container之间想共享文件可以是用emptyDir或hostPath等。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: phpfpm
  labels:
    name: phpfpm
spec:
  replicas: 1
  selector:
    matchLabels:
      app: phpfpm
  template:
    metadata:
      labels:
        app: phpfpm
    spec:
      containers:
      - name: php
        image: php-fpm3
        imagePullPolicy: IfNotPresent 
        volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: nginx-data
        - mountPath: /tmp
          name: temp
        ports:
        - containerPort: 9000
  
      - name: nginx
        image: mynginx3
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: nginx-data
        - mountPath: /tmp
          name: temp

      volumes:
      - name: nginx-data
        configMap:
          name: nginx-data
          items:
          - key: index.php
            path: index.php
      - name: temp
        emptyDir: {}
View Code

namespace:

同一namespace的pod可以直接通过service name访问,不同namespace之间必须通过FQDN访问(service_name.namespace_name.svc.cluster.local),并不是所有资源都必须在名称空间,命名空间资源本身并不在命名空间中。并且低级资源(例如节点和persistentVolumes)不在任何名称空间中。名称空间用来隔离不同用户或者不同业务线。

label:

label不同于name与uuid,前者在同一namspec不能重复,而label在同一名称空间内可以重复,用来表示具有相同属性的一组资源。

基于label筛选:

ubectl get pods -l environment=production,tier=frontend
kubectl get pods -l 'environment in (production),tier in (frontend)'
kubectl get pods -l 'environment in (production, qa)'
kubectl get pods -l 'environment,environment notin (frontend)'

创建资源的方式:

1命令式:

kubectl run nginx --image nginx
kubectl create deployment nginx --image nginx

 2.申明式:

 kubectl apply -f nginx.yml   #根据yml创建,如果之前不存在就创建,存在则判断是否有过更改,有则跟新,否则不变化。

kubectl replace -f nginx.yaml   #根据配置文件覆盖原有资源
kubectl diff -f nginx.yml #检测运行的资源与配置文件中是否存在变化

递归处理目录:

kubectl diff -R -f configs/
kubectl apply -R -f configs/


 

service工作模型:userspace,iptables,ipvs

#headless(无头ip),直接将cluster_name映射到podip,而非cluster_ip:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: default
spec:
selector:
app: nginx
clusterIP: None
ports:
- name: nginx
port: 80
targetPort: 80


##############sesion绑定
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: default
spec:
selector:
app: nginx
type: NodePort
sessionAffinity: ClientIP
ports:
- name: nginx
port: 80
targetPort: 80
nodePort: 44444
###############
ingress_control:k8s的默认service是基于4层,无法代理https请求,如果我们的网站是https,这时就需要使用支持https的反向代理,例如ingress-nginx/traefik/Envoy(专为容器代理而生),这些都都称为ingress_control
ingress:k8s的一种资源,用于定义ingress_control的配置文件信息,例如后端服务器,主机名,ssl证书路径等
注意:必须保证ingress_control能被节点外的用户访问,可以给ingress_control创建服务,或者直接使用主机网络名称空间。

后端pods创建service并不是为了暴露端口,而是利用service做分组功能,这样ingress_control就可以通过服务名对应到后端的pods:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: default
spec:
selector:
app: nginx
ports:
- name: nginx
port: 80
targetPort: 80

#################
K8S支持的存储方式:
1.voluems
2.pvc

PVC:PVC与PV只能一一对应,
PV:PV不能指定namespace,因为pv属于集群而不是pod
voluems:
emptyDir:在宿主机的内存或磁盘划出一块磁盘使用,随着pod消失而消失。
gitRepo:只能pull仓库数据,不能直接往仓库push,挂载中如果仓库新push了数据,container不能实时刷新
hostPath:挂在宿主机磁盘路劲到container

NOTE: subPath 与mountPath:

volumeMounts:
    - name: nginx-data
       mountPath: /etc/sysctl.d/index.php
       subPath: index.php

如果写了subPath,mountPath就必须写全路径,subPath用来表示哪一段是文件,这样就算之前文件夹中有文件也不会被覆盖

volumeMounts:
    - name: nginx-data
       mountPath: /etc/sysctl.d

如果没有subPath选项,挂载后容器sysctl.d目录下原有的文件会被覆盖(不会删除,只是不可见而已)
View Code


storageClass:我们用PVC关联pv后,只需将pod关联到相关pvc,然后container挂在pod中上关联的pvc就可以最终实现pod到存储的关联,但是这种方式必须手动创建后端相关的存储,否则pvc将一直处于pending状态,引入存储类后就可以实现当pods想挂在某类型存储时,storageClass自动调用后端存储接口创建对应规格存储(要求后端存储具有restful风格的交互接口)。

注意:
1.pvc的accessModes必须是pv accessModes的子集,而且pv要有pvc需要的容量,否则pv一直会卡在pending状态
2.pv与pvc关联后如果数据重要千万不能删除pv,一旦pv显示Released状态时,新的pvc或者新建的与之前同名的pvc都无法再次绑定到相同pv


Pv 回收策略:
1.Delete:当pvc与pv解除绑定后自动删除pv与volume中的内容,需要存储类支持
2.Recycle:当pvc与pv解除绑定后自动删除volume中的内容,仅支持NFS/HOST Drectory
3.Retain:当pvc与pv解除绑定后保留pv和volume中的内容,需要手动清理
###################
configmap/secret
configmap:明文存放
secret:base64加密存放(并非安全,可以利用base64反向解密)

传入方式:
1.env :此方式不能实现动态更新,如果改变了configmap/secret的值,不能及时生效,只在容器建立那一刻读取
2.挂载:此方式可以动态更新,当作一个特殊的磁盘挂载进去,文件的内容就是传入的configmap/secret的内容

NOTE:

我们在创建configmap时如果想保留换行符,必须告诉yaml把我们输入的数据当做长文本处理,这时可以加一个"|"

eg:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-conf
  namespace: default

data:
  nginx.conf: |
    server {
            listen       80 default_server;
            listen       [::]:80 default_server;
            server_name  _;
            root         /usr/share/nginx/html;
            #delete line
            include /etc/nginx/default.d/*.conf;
            location / {
            }
        location ~ .php$ {
            fastcgi_pass   php:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
            error_page 404 /404.html;
                location = /40x.html {
            }
            error_page 500 502 503 504 /50x.html;
                location = /50x.html {
            }
View Code

如果我们在开头加了|还是不能保留格式,这时候需要检查文本末尾是否有多余的空格,(VIM编辑器在命令模式输入:set list 就可以查看)


###################
stateFulSet:管理有状态的服务,例如redis集群,顺序启动,反序停止
updateStrategy:
rollingUpdate:partition <int> #设置更新策略,更新>=<int>的container
volumeClaimTemplates:自动建立PVC关联container,但是pv需要我们首先定义好
注意:目前k8s管理有状态的服务还是不太成熟,且需要考虑的意外情况太多,不建议将有状态服务迁移到 k8s

###################
k8s有两种账户:
1.user_account:用户操作k8s集群时需要提供的账号
2.service_account:pod连接k8s时用到的账号,每个pod创建时会自动使用默认account,我们也可以手动指定
pod在pull私有仓库时的认证信息可以直接使用pod中的imagePullSecrets,也可以将认证信息放到用户账号的image pull secrets,然后用serviceAccountName字段关联账户到pod上即可。
3.如果给予rbac验证方法,默认配置文件存放于当前系统账号家目录.kube/config 文件中
role=资源+可以操作的权限
rolebinding=用户+role
##rolebinding可以指定某个用户在某个名称空间中所拥有的权限(名称空间级别)
##clusterrolebing可以指定某个用户在某个k8s集群中所拥有的权限(集群级别)
rolebinding可以直接与clusterrole绑定这样可以指定某个用户在集群中可以对哪些名称空间有相同权限:
kubectl create clusterrole showtestpods --verb=get,list,watch --resource=pods,pods/status
kubectl create rolebinding showtestpods --clusterrole=showtestpods --user=test --namespace=test1
kubectl create rolebinding showtestpods --clusterrole=showtestpods --user=test --namespace=test2
#用户test可以查看namespace=test1和test2中的pod状态,如果我们用role+rolebinding这样也可以完成,但是很麻烦,需要在每个名称空间定义role,而使用rolebinding+clusterrole只需定义一次clusterrole。

###########
flannel工作模式:
1.vxlan:给予隧道
2.vxlan和Directrouting(host-gw),flannel自动判定,当物理节点处于同一二层网络时使用host-gw,否则使用vxlan,配置方式:
{
"Network":"10.254.0.0/16",
"Backend":{
"type":"vxlan",
"Directrouting:true
}
}

host-gw:性能最好,但是必须要求所有物理节点处于同一二层网络
udp:性能最差

########
网络策略,限制k8s中网络访问规则,
(最好使用kubeadm安装集群,手动安装k8s集群如果有些参数配置不正确会导致calic无法运行。)
policyTypes 指定那个规则 那个规则生效,不指定就是默认规则(默认是允许所有)
如果policyTypes指定了规则,而那个规则我们没有定义,那么就是拒绝
spec:
podSelector: {}
ingress:
- {}
policyTypes:
- Ingress
###表示允许所有ingress

spec:
podSelector: {}
policyTypes:
- Ingress
###表示拒绝所有ingress

#影响调度方式:
1.taint:
如果在节点上标记了taint,那么在pod上就必须定义tolerations。
master上默认被标记了污点,默认非系统服务pod不会被调度到master上运行,如果要master运行pod,需要删除默认污点,kubectl taint nodes node1 node-role.kubernetes.io/master-
2.nodeselector
kubectl explain pod.spec
(1)nodeSelector:选择node亲和性,更倾向于运行在那些node上
(2)nodeName:只运行在那个node上
3.affinity(亲和性)
(1)nodeAffinity:pod更倾向于运行在那个节点
(2)podAffinity:哪些pod更倾向于运行在一起(虽然nodeAffinity也能完成,但是podAffinity可以更细粒度,比如定义哪些pod运行在同一机柜,同一机房等,但是nodeAffinity就需要更精确的规划lables,更加繁琐)


#############
容器资源限制及监控:
资源限制:
kubectl explain pod.spec.containers.resource
(容器对资源的限制可能不是很精确)
监控:
kubectl top node/pod #要想使用必须安装heapster,kubernets1.1之前的版本可以使用heapster,之后版本抛弃了heapster,转而使用metrics-server
metrics-server:获取核心指标(cpu,memory)
prometheus:可以定义其监控我们自定义的指标
注意:如果我们想要使用aotu_scale,就必须保证k8s能够读取各pod的资源使用情况,可以使用kubectl top pod 测试metrices-server是否工作正常

https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/metrics-server

k8s 1.13 安装metric-server:
https://github.com/kubernetes-incubator/metrics-server/tree/master/deploy/1.8%2B
排错:
提示:unable to fully collect metrics: [unable to fully scrape metrics from source kubelet_summary:xxx: unable to fetch metrics from Kubelet ... (X.X): Get https:....: x509: cannot validate certificate for 1x.x.

解决:container加入:
ommand:
- /metrics-server
- --kubelet-insecure-tls
- --kubelet-preferred-address-types=InternalIP

https://stackoverflow.com/questions/53392609/unable-to-fully-collect-metrics-when-installing-metric-server

auto-scale:
autoscaling/v2beta1:只能以cpu为指标
autoscaling/v2beta2:可以以cpu或内存为指标

安装普鲁米修斯:
https://github.com/iKubernetes/k8s-prom #prometheus 安装文件
https://github.com/DirectXMan12/k8s-prometheus-adapter #安装后由于版本不兼容要替换为此处的prometheus-adapter


helm:k8s包管理器:
inkubator:helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com/
stable:helm repo add stable https://charts.ost.ai
helm delete --purge mysql #如果之前运行chart使用了相同的名称,必须删除了名称才可以再次运行


其他相关:
master节点高可用(kubuadm可以创建)
kubernets federation:联邦,不同k8s集群之间相互调度
priorityClass:定义不同pod优先级
limitRange:设置默认资源使用限制策略
PSP(pod安全策略):
SecurityContext:类似于PSP


kubernets三层封装:
openshift
rancher

排错:

一.etcd 挂在nfs做数据盘时启动etcd 报错:

 etcdserver: create wal error: bad file descriptor

原因:etcd在获取nfs上的文件锁时遇到问题。对于Linux内核版本> = 3.15 ,nfs上的文件锁定应该在etcd 3.0中工作
解决:使用etcd3.x 版本即可解决

原文地址:https://www.cnblogs.com/dufeixiang/p/10802033.html