k8s详解基本对象 电脑版发表于:2020/4/11 9:38  >#k8s详解基本对象 [TOC] <br/> ### 参考yaml代码如下 ```bash apiVersion: apps/v1 kind: Deployment metadata: name: k8s-demo namespace: netcore labels: name: k8s-demo spec: replicas: 2 selector: matchLabels: name: k8s-demo template: metadata: labels: name: k8s-demo spec: containers: - name: k8s-demo image: aidasi/k8sdemoapi:v1 ports: - containerPort: 80 imagePullPolicy: Always --- kind: Service apiVersion: v1 metadata: name: k8s-demo namespace: netcore spec: type: NodePort ports: - port: 80 targetPort: 80 selector: name: k8s-demo ``` <br/> Lable & Selector ------------ #### 特点 - 自定义标签方便分组与筛选 <br/> #### Service 关联 Pod <br/> >```flow st=>start: kind:Service(k8s-demo)|current op=>operation: Selector op1=>operation: 筛选Lables中name为k8s-demo的Pod e=>end: 发布服务|past st->op->op1->e ``` `【注意】此时的Pod为template->metadata->labels` <br/> #### MatchLabels 关联 Containers <br/> >```flow st=>start: MatchLabels|current op=>operation: Selector 筛选条件(=,!=,in,not in,and) op0=>operation: name: ! k8s-demo(name不等于k8s-demo的进行筛选) op1=>operation: 筛选Containers中条件符合 e=>end: 筛选容器结束|past st->op->op0->op1->e ``` 当然还可以这样进行筛选 ```bash selector: matchLabels: component: redis matchExpressions: - {key: tier, operator: In, values: [cache]} - {key: environment, operator: NotIn, values: [dev]} ``` **Kind** `Job` `Deployment` `Replica Set` `Daemon Set` >matchLabels 是由 {key,value} 对组成的映射。matchLabels 映射中的单个 {key,value } 等同于 matchExpressions 的元素,其 key字段为 “key”,operator 为 “In”,而 values 数组仅包含 “value”。matchExpressions 是 pod 选择器要求的列表。有效的运算符包括 In,NotIn,Exists 和 DoesNotExist。在 In 和 NotIn 的情况下,设置的值必须是非空的。来自 matchLabels 和 matchExpressions 的所有要求都是合在一起 – 它们必须都满足才能匹配。 <br/> #### Deployment.metadata.labels 关联 MatchLabels <br/> >```flow st=>start: Deployment.metadata.labels|current op=>operation: labels 筛选 MatchLabels e=>end: 筛选Replica Set结束|past st->op->e ``` <br/> Pod ------------ <br/> #### 特点 - 解耦控制器和服务,管理器只需要监控Pod即可 - 无状态 - 高可用,当出现一些删除pod的操作时,会自动创建新的pod <br/> <br/> #### livenessProbe Pod探针 <br/> 在yaml文件中的代码如下代码 ```bash livenessProbe: httpGet: path: /healthz port: 80 timeoutSeconds: 5 ``` 完整代码如下 ```bash apiVersion: apps/v1 kind: Deployment metadata: name: k8s-demo namespace: netcore labels: name: k8s-demo spec: replicas: 2 selector: matchLabels: name: k8s-demo template: metadata: labels: name: k8s-demo spec: containers: - name: k8s-demo image: aidasi/k8sdemoapi:v1 ports: - containerPort: 80 imagePullPolicy: Always livenessProbe: httpGet: path: /healthz port: 80 timeoutSeconds: 5 --- kind: Service apiVersion: v1 metadata: name: k8s-demo namespace: netcore spec: type: NodePort ports: - port: 80 targetPort: 80 selector: name: k8s-demo ``` 部署的时候,当没有相关接口做探针时 通过Kubernetes Dashboard来查看  ><font style="color:#e67e22;font-size:26px">结果也是不可以被访问的</font> <br/> #### readinessProbe Pod探针 <br/> 在yaml文件中的代码如下代码 ```bash readinessProbe: httpGet: path: /healthz port: 80 timeoutSeconds: 5 ``` 完整代码如下 ```bash apiVersion: apps/v1 kind: Deployment metadata: name: k8s-demo namespace: netcore labels: name: k8s-demo spec: replicas: 2 selector: matchLabels: name: k8s-demo template: metadata: labels: name: k8s-demo spec: containers: - name: k8s-demo image: aidasi/k8sdemoapi:v1 ports: - containerPort: 80 imagePullPolicy: Always livenessProbe: httpGet: path: /WeatherForecast/1 port: 80 timeoutSeconds: 5 readinessProbe: httpGet: path: /healthz port: 80 timeoutSeconds: 5 --- kind: Service apiVersion: v1 metadata: name: k8s-demo namespace: netcore spec: type: NodePort ports: - port: 80 targetPort: 80 selector: name: k8s-demo ``` 查看结果 我这边仍然不可访问 但据教程说是可以继续被请求的  当对代码进行一定的修改 这个时候是都可以访问的时候 ```bash livenessProbe: httpGet: path: /WeatherForecast/1 port: 80 timeoutSeconds: 5 readinessProbe: httpGet: path: /WeatherForecast/1 port: 80 timeoutSeconds: 5 ``` 通过`kubectl apply -f deploy.yaml` 结果如下:  探针大致就这些! <br/> #### RestartPolicy 重启策略 <br/> >PodSpec 中有一个 **restartPolicy** 字段,可能的值为 `Always`、`OnFailure` 和 `Never`。默认为 `Always`。 **restartPolicy** 适用于 Pod 中的所有容器。**restartPolicy** 仅指通过同一节点上的 kubelet 重新启动容器。 失败的容器由 kubelet 以五分钟为上限的指数退避延迟(10秒,20秒,40秒…)重新启动,并在成功执行十分钟后重置。如 Pod 文档 中所述,一旦绑定到一个节点,Pod 将永远不会重新绑定到另一个节点。 <br/> #### imagePullPolicy 拉取镜像策略 <br/> >支持三种imagePullPolicy >- Always: 不管镜像是否存在都会进行一次拉取 (使用时修改yaml:`image: aidasi/k8sdemoapi:latest`) >- Never: 不管镜像是否存在都不会进行拉取 >- IfNotPresent: 只有镜像不存在时,才会进行镜像拉取 (default) <br/> #### Resources 资源限制 <br/> 在containers中添加如下yaml ```bash resources: requests: cpu: "300m" memory: "56Mi" limits: cpu: "500m" memory: "128Mi" ``` >Kubernetes通过cgroups限制容器的CPU和内存等计算资源,包括requests(请求,调度器保证调度到资源充足的Node上)和limits(上限)等: >>- spec.containers[].resources.**limits.cpu**:CPU上限,可以短暂超过,容器也不会被停止 - spec.containers[].resources.**limits.memory**:内存上限,不可以超过;如果超过,容器可能会被停止或调度到其他资源充足的机器上 - spec.containers[].resources.**requests.cpu**:CPU请求,可以超过 - spec.containers[].resources.**requests.memory**:内存请求,可以超过;但如果超过,容器可能会在Node内存不足时清理 <br/> #### 初始容器 Container (Init Container) <br/> >**Init Container**在所有容器运行之前执行(**run-to-completion**),常用来初始化配置。 在spec下添加如下操作 ```bash initContainers: - name: install image: busybox command: - wget - "-O" - "/work-dir/index.html" - http://kubernetes.io volumeMounts: - name: workdir mountPath: "/work-dir" ``` <br/> #### 容器生命周期钩子 <br/> >容器生命周期钩子(Container Lifecycle Hooks)监听容器生命周期的特定事件,并在事件发生时执行已注册的回调函数。支持两种钩子。 >>**postStart**: 容器启动后执行,注意由于是异步执行,它无法保证一定在ENTRYPOINT之后运行。如果失败,容器会被杀死,并根据RestartPolicy决定是否重启 >>**preStop**:容器停止前执行,常用于资源清理。如果失败,容器同样也会被杀死 >而钩子的回调函数支持两种方式: >>**exec**:在容器内执行命令 >>**httpGet**:向指定URL发起GET请求 ```bash apiVersion: v1 kind: Pod metadata: name: lifecycle-demo spec: containers: - name: lifecycle-demo-container image: nginx lifecycle: postStart: exec: command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"] preStop: exec: command: ["/usr/sbin/nginx","-s","quit"] ``` <br/> #### 指定Node <br/> >通过**nodeSelector**,一个**Pod**可以指定它所想要运行的**Node**节点。 首先给**Node**加上标签: ```bash kubectl label nodes <YourNodeName> nodetypeis=hmy ``` 接着,指定该**Pod**只想运行在带有**nodetypeis=hmy**标签的**Node**上: ```bash apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: nodetypeis: hmy ``` <br/> #### 使用Capabilities <br/> >默认情况下,容器都是以非特权容器的方式运行。比如,不能在容器中创建虚拟网卡、配置虚拟网络。 >##### Kubernetes提供了修改Capabilities的机制,可以按需要给给容器增加或删除。比如下面的配置给容器增加了CAP_NET_ADMIN并删除了CAP_KILL。 ```bash apiVersion: v1 kind: Pod metadata: name: hello-world spec: containers: - name: friendly-container image: "alpine:3.4" command: ["/bin/echo", "hello", "world"] securityContext: capabilities: add: - NET_ADMIN drop: - KILL ``` <br/> #### 限制网络带宽 <br/> >**Ingress** >可以通过给**Pod**增加**kubernetes.io/ingress-bandwidth**和**kubernetes.io/egress-bandwidth**这两个**annotation**来限制**Pod**的网络带宽 ````bash apiVersion: v1 kind: Pod metadata: name: qos annotations: kubernetes.io/ingress-bandwidth: 3M kubernetes.io/egress-bandwidth: 4M spec: containers: - name: iperf3 image: networkstatic/iperf3 command: - iperf3 - -s ```` <br/> Service ------------ <br/> >#### Service版本发展史 - 初代Service客户端通过kubectl-proxy作代理访问,算法基于轮询的方式 - 二代Service客户端通过集群ip进行访问,算法是通过负载均衡的方式进行分发请求 - 三代Service与二代相通,只是请求访问的算法方式增加了 <br/> >#### 特点 - 解耦控制器和服务,管理器只需要监控Pod即可 - 无状态 - 高可用,当出现一些删除pod的操作时,会自动创建新的pod  <br/> Namespace ------------ #### 特点 - 有些对象和**namespace**相关,而有些则不受**namespace**管辖 - 可以借助于 **resource quote** 来控制 **namespace** 的资源 <br/> #### namespace 相关常规操作 <br/> >查询所有**namespace** ```bash kubectl get namespace 或 kubectl get ns ``` >创建**namespace** ```bash kubectl create namespace myspace ``` >删除**namespace** 注意:把**namespace**删除也就意味着删除下面的所有资源 ```bash kubectl delete namespace myspace ``` <br/> #### 通过 quote 对 namespace 的请求与限制 <br/> >创建一个名为**myspace**的**namespace** ```bash kubectl create namespace myspace ``` >创建一个基本的**compute-resources.yaml** 限制yaml ```bash cat <<EOF > compute-resources.yaml apiVersion: v1 kind: ResourceQuota metadata: name: compute-resources spec: hard: requests.cpu: "1" requests.memory: 1Gi limits.cpu: "2" limits.memory: 2Gi requests.nvidia.com/gpu: 4 EOF ``` | 名称 | 定义 | | ------------ | ------------ | | requests.cpu | 需要的**cpu**个数 | | requests.memory | 需要的内存大小 | | limits.cpu | 限制**cpu**的个数 | | limits.memory | 限制**memory**的内存大小 | | requests.nvidia.com/gpu | 请求的GPU总数限制为4 | >限制到**namespace** **myspace**中去 ```bash kubectl create -f ./compute-resources.yaml --namespace=myspace ``` >创建一个高级的**object-counts.yaml** 限制yaml ```bash cat <<EOF > object-counts.yaml apiVersion: v1 kind: ResourceQuota metadata: name: object-counts spec: hard: configmaps: "10" persistentvolumeclaims: "4" pods: "4" replicationcontrollers: "20" secrets: "10" services: "10" services.loadbalancers: "2" EOF ``` | 名称 | 定义 | | ------------ | ------------ | | configmaps | 命名空间中可以存在的配置映射总数。 | | persistentvolumeclaims | 命名空间中可以存在的持久卷声明的总数。 | | pods | 命名空间中可以存在的处于非终端状态的Pod总数。如果.status.phase in (Failed, Succeeded)为true,则Pod处于终端状态。 | | replicationcontrollers | 命名空间中可以存在的复制控制器的总数。 | | secrets | 命名空间中可以存在的秘密总数。 | | services | 命名空间中可以存在的服务总数。 | | services.loadbalancers | 命名空间中可以存在的负载均衡器类型的服务总数。 | >限制到**namespace** **myspace**中去 ```bash kubectl create -f ./compute-resources.yaml --namespace=myspace ``` >查看限制 ```bash kubectl get quota --namespace=myspace ``` >查看指定命名空间详细配置 ```bash kubectl describe quota compute-resources --namespace=myspace ``` >更多请参考 https://kubernetes.io/docs/concepts/policy/resource-quotas/ <br/> Volume ------------ #### 特点 - 对资源进行存储并管理 <br/> #### emptyDir <br/> >一个 **emptyDir** 第一次创建是在一个 **pod** 被指定到具体 **node** 的时候,并且会一直存在在 **pod** 的生命周期当中,正如它的名字一样,它初始化是一个空的目录,**pod** 中的容器都可以读写这个目录,这个目录可以被挂在到各个容器相同或者不相同的的路径下。当一个 **pod** 因为任何原因被移除的时候,这些数据会被永久删除。 <br/> >如下图所示: <br/> ```flow st=>start: 创建pod|current emptyDir=>condition: 创建emptyDir(no,yes无效)|current op=>operation: pod挂掉 node=>operation: 在node上创建一块新的空间 e=>end: emptyDir数据被删除,node上的数据也被删除|past st->emptyDir->op->e emptyDir(no)->node emptyDir(yes)->op->e ``` <br/> #### hostPath <br/> >挂载到本机(可进行长期存储) <br/> #### secret <br/> >可以以键值对的方式存储密码与数据 <br/> #### persistentVolumeClaim <br/> >可以实现一些云存储或分布式存储