关于k8s:K8S实战十二-为-Ingress-以及后端-Nginx-增加证书

前言后面 nginx 都是 http 协定在工作,那么加证书应该如何操作。 更新历史20200701 - 初稿 - 左程立原文地址 - https://blog.zuolinux.com/2020/07/01/nginx-https.html创立证书能够网上申请一年收费证书,也能够自建证书。上面自建证书。 下载自建证书脚本 wget -O Makefile https://raw.githubusercontent.com/kubernetes/examples/master/staging/https-nginx/Makefile创立证书文件 make keys KEY=/tmp/nginx.key CERT=/tmp/nginx.crt将证书写入到 K8S 的 secret 中 # kubectl create secret tls nginxsecret --key /tmp/nginx.key --cert /tmp/nginx.crtsecret/nginxsecret created将 nginx 配置写入到 K8S 的 configmap 中 # cat default.confserver { listen 80 default_server; listen [::]:80 default_server ipv6only=on; listen 443 ssl; root /usr/share/nginx/html; index index.html; server_name localhost; ssl_certificate /etc/nginx/ssl/tls.crt; ssl_certificate_key /etc/nginx/ssl/tls.key; location / { try_files $uri $uri/ =404; }}# kubectl create configmap nginxconfigmap --from-file=default.confconfigmap/nginxconfigmap created整合后端 Pod 和证书,应用 Service 公布[root@master01 ~]# cat nginx-app.yaml apiVersion: v1kind: Servicemetadata: name: my-nginx labels: run: my-nginxspec: type: NodePort ports: - port: 8080 targetPort: 80 protocol: TCP name: http - port: 443 protocol: TCP name: https selector: run: my-nginx---apiVersion: apps/v1kind: Deploymentmetadata: name: my-nginxspec: selector: matchLabels: run: my-nginx replicas: 1 template: metadata: labels: run: my-nginx spec: volumes: - name: secret-volume secret: secretName: nginxsecret - name: configmap-volume configMap: name: nginxconfigmap containers: - name: nginxhttps image: bprashanth/nginxhttps:1.0 ports: - containerPort: 443 - containerPort: 80 volumeMounts: - mountPath: /etc/nginx/ssl name: secret-volume - mountPath: /etc/nginx/conf.d name: configmap-volume[root@master01 ~]# kubectl apply -f nginx-app.yaml service/my-nginx createddeployment.apps/my-nginx created查看运行状况 ...

September 18, 2020 · 2 min · jiezi

关于k8s:K8S实战十-Service

前言Pod 曾经胜利运行起来了,然而有两个问题。 一是这些 Pod 无奈从集群内部间接拜访到,二是 Pod 呈现故障自愈后,IP 会发生变化。 如何解决这两个问题,这里有一个十分重要的概念:Service 更新历史20200625 - 初稿 - 左程立原文地址 - https://blog.zuolinux.com/2020/06/25/about-service.htmlService 的意义和特点对一组 Pod 提供负载平衡(工作在 TCP/UDP 4 层)避免 Pod 更换 IP 失联,即服务发现通过 label selector 关联 PodService 工作原理Service 是由 kube-proxy 组件加上 iptables/LVS 独特实现。说白了就是通过 kube-proxy 生成了一堆 iptables 规定,通过 iptables 规定来转发数据。 iptables 转发: K8S 默认的转发设置。抉择后端 Pod 为随机抉择。当 Pod 没有响应,连贯会失败,并没有健康检查机制。须要配合 Pod 就绪探测器来确保拜访到衰弱的 Pod。当集群规模达到上万个服务时,iptables 转发效率会显著升高。LVS转发: 基于内核哈希表,性能弱小,具备更高网络吞吐量。实用于 Pod 量级大,转发规定更多的大规模集群。LVS 反对更多的 Pod 负载平衡调度算法。LVS 只负责负载平衡和代理性能,残余的包过滤和SNAT等操作还是须要 iptables 解决,但这些操作规定数量不会因 Pod 数量的减少而减少。也叫 IPVS 。Service 的默认工作形式创立 Pod 和 默认Service,进行默认工作状态的测试。 ...

September 18, 2020 · 3 min · jiezi

关于k8s:K8S实战八-Job-和-CronJob

前言容器分为两类 在线业务 - 服务类容器须要继续不中断的提供服务,容器须要始终运行 离线业务 - 工作类容器个别执行一次性工作,比方统计日志数据等,运行实现后容器即可敞开 更新历史20200618 - 初稿 - 左程立原文地址 - https://blog.zuolinux.com/2020/06/18/controller-job-cronjob.htmlJobcat job.yaml apiVersion: batch/v1kind: Jobmetadata: name: job-testspec: template: metadata: name: job-test spec: containers: - name: test-job image: busybox command: ["echo", "test job!"] restartPolicy: Never参数restartPolicy 只能是 Never 或者 onFailure 启动 [root@master01 ~]# kubectl apply -f job.yaml job.batch/job-test created运行状态 [root@master01 ~]# kubectl get podNAME READY STATUS RESTARTS AGEjob-test-t2gbw 0/1 ContainerCreating 0 12s[root@master01 ~]# kubectl get podNAME READY STATUS RESTARTS AGEjob-test-t2gbw 0/1 Completed 0 24s查看运行后果 ...

September 18, 2020 · 3 min · jiezi

关于k8s:K8S实战七-有状态应用之-MySQL-集群

前言本节应用 StatefulSet 控制器部署一个 MySQL 集群,而后进行宕机测试,察看集群是否能够失常复原应用并且不失落数据。 实现的集群有如下特色: 是一个主从复制的 MySQL 集群1 个主节点, 多个从节点从节点可能程度扩大所有的写操作,只能在主节点上执行读操作能够在所有节点上执行更新历史20200615 - 初稿 - 左程立原文地址 - https://blog.zuolinux.com/2020/06/15/statefulset-mysql-cluster.html所需服务资源所需资源为: 一个 ConfigMap两个 Service一个 StatefulSetConfigMapkubectl apply -f https://k8s.io/examples/application/mysql/mysql-configmap.yamlServicekubectl apply -f https://k8s.io/examples/application/mysql/mysql-services.yamlMySQL StatefulSetwget https://k8s.io/examples/application/mysql/mysql-statefulset.yaml批改 mysql-statefulset.yaml, 应用上一节创立的 NFS 动静存储卷 volumeClaimTemplates: - metadata: name: data annotations: volume.beta.kubernetes.io/storage-class: managed-nfs-storage spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 1Gi创立 MySQL 有状态利用 kubectl apply mysql-statefulset.yaml写入数据测试写入数据 kubectl run mysql-client --image=mysql:5.7 -i --rm --restart=Never -- mysql -h mysql-0.mysql <<EOFCREATE DATABASE test;CREATE TABLE test.messages (message VARCHAR(250));INSERT INTO test.messages VALUES ('hello');EOF查看从机是否能够读取到数据 ...

September 18, 2020 · 2 min · jiezi

关于k8s:云图说-通过Helm模板快速部署中间件应用

摘要:通过全容器化Helm模板,疾速部署中间件利用。云容器引擎基于Kubernetes Helm规范的模板提供对立的资源管理与调度,高效地实现了模板的疾速部署与前期治理,大幅简化了Kubernetes资源的装置治理过程。 Helm是治理Kubernetes应用程序的打包工具。 点击“理解更多”,对于CCE,你想晓得的都在这里! 号外!!!华为云官网开发者推广招募打算正在炽热进行中,点击立刻理解详情 点击关注,第一工夫理解华为云陈腐技术~

September 18, 2020 · 1 min · jiezi

关于k8s:Jenkins-X-3x-alpha初见面

Jenkins X很棒的改良 作者:James Strachan 咱们非常高兴地发表Jenkins X版本3的alpha公布。 你能够在这里浏览更多对于架构和组件的概述。 与版本2相比,该版本有很多长处,更易于应用、了解和治理。对于不同的基础设施和云提供商,它的配置更加灵便和简略。 新版本与helm 3、helmfile、kpt和/或kustomize的任何组合都能很好地工作。 对于那些应用过Jenkins X版本2的人,你能够查看两个版本的比拟。 咱们还通过新的jx-preview插件增加了基于helmfile的预览环境加强,这使得制作更简单的预览更加容易,比方: 为预览应用多个命名空间应用每个预览命名空间或将预览部署到共享命名空间(例如通过Canaries)应用helmfile革除资源咱们当初通过Terraform为三大公共云中的两大云提供了反对: 亚马逊谷歌Azure的反对越来越靠近了;如果你想帮忙它做好筹备,退出咱们的slack。 当应用你的笔记本电脑或本地kubernetes集群不应用terraform,咱们反对: Minikube这样你就能够在笔记本电脑上运行Jenkins X了On Premise这样你就能够应用任何的kubernetes集群咱们正在致力改善装置/降级的用户体验;咱们心愿很快就能有一种纯正的terraform(或terraform云)形式来在私有云上启动Jenkins X的装置,并缩小工作量。咱们心愿很快就能在博客上写进去…… 所以请应用并让咱们晓得你的想法吧!如果你能想到任何咱们能够改良的办法,请通知咱们! 点击浏览网站原文。 为下一代继续交付合作提供一个中立的家。 CDF(Continuous Delivery Foundation,继续交付基金会)是许多快速增长的继续交付我的项目,包含Jenkins、Jenkins X、Spinnaker和Tekton,的供应商中立家园。CDF通过凋谢模型、培训、行业指南和可移植性重点来反对DevOps从业者。 Linux基金会是非营利性组织,是技术生态系统的重要组成部分。Linux基金会通过提供财务和智力资源、基础设施、服务、流动以及培训来反对创立永续开源生态系统。在共享技术的创立中,Linux基金会及其我的项目通过共同努力造成了不凡胜利的投资。扫描二维码关注LFAPAC微信公众号。

September 18, 2020 · 1 min · jiezi

关于k8s:EIK收集日志

装置配置elasticsearch下载helm包helm pull elastic/elasticsearch容器中生成elastic证书#!/bin/bashRELEASE=7.9.1docker run --name elastic-charts-certs -i -w /app \ harbor-k8s.iwgame.com/containers/elasticsearch:$RELEASE \ /bin/sh -c " \ elasticsearch-certutil ca --out /app/elastic-stack-ca.p12 --pass '' && \ elasticsearch-certutil cert --name security-master --dns security-master --ca /app/elastic-stack-ca.p12 --pass '' --ca-pass '' --out /app/elastic-certificates.p12" && \docker cp elastic-charts-certs:/app/elastic-certificates.p12 ./ && \docker rm -f elastic-charts-certs && \openssl pkcs12 -nodes -passin pass:'' -in elastic-certificates.p12 -out elastic-certificate.pem创立secrets生成账号密码和证书kubectl create secret -n efk generic elastic-certificates --from-file=elastic-certificates.p12kubectl create secret -n efk generic elastic-certificate-pem --from-file=elastic-certificate.pemkubectl create secret -n efk generic elastic-credentials --from-literal=password=123 --from-literal=username=elastic批改values.yaml文件volumeClaimTemplate: accessModes: [ "ReadWriteOnce" ] storageClassName: "iwgame-nfs-storage" resources: requests: storage: 30GiesConfig: elasticsearch.yml: | cluster.name: "docker-cluster" network.host: 0.0.0.0 xpack.security.enabled: true xpack.security.transport.ssl.verification_mode: certificate xpack.security.transport.ssl.enabled: true xpack.security.transport.ssl.keystore.path: /usr/share/elasticsearch/config/certs/elastic-certificates.p12 xpack.security.transport.ssl.truststore.path: /usr/share/elasticsearch/config/certs/elastic-certificates.p12extraEnvs: - name: ELASTIC_PASSWORD valueFrom: secretKeyRef: name: elastic-credentials key: password - name: ELASTIC_USERNAME valueFrom: secretKeyRef: name: elastic-credentials key: usernamesecretMounts: - name: elastic-certificates secretName: elastic-certificates path: /usr/share/elasticsearch/config/certs装置elasticsearchhelm install --namespace=logging elastic ./查看pod运行状态个别都须要装置奇数,因为我只有两个node所以部署了2个,生产环境倡议装置三个 ...

September 17, 2020 · 2 min · jiezi

关于k8s:centos7使用Minikube快速搭建出Kubernetes本地实验环境踩坑集锦及解决方案

centos7应用Minikube"疾速搭建"出Kubernetes本地试验环境(踩坑集锦及解决方案)先决条件 查看Linux是否反对虚拟化,验证输入是否为非空如何开启虚拟化grep -E --color 'vmx|svm' /proc/cpuinfo 装置 kubectl判断是否胜利装置kubectl kubectl version 装置MinikubeLinux curl -Lo minikube https://kubernetes.oss-cn-han... && chmod +x minikube && sudo mv minikube /usr/local/bin/ 启动minikube start 为了拜访海内的资源,阿里云提供了一系列基础设施,请依照如下参数进行配置。其中常见参数 --driver=*** 从1.5.0版本开始,Minikube缺省应用本地最好的驱动来创立Kubernetes本地环境,测试过的版本 docker, kvm--image-mirror-country cn 将缺省利用 registry.cn-hangzhou.aliyuncs.com/google_containers 作为装置Kubernetes的容器镜像仓库 (阿里云版本可选)--iso-url=*** 利用阿里云的镜像地址下载相应的 .iso 文件 (阿里云版本可选)--registry-mirror=***为了拉取Docker Hub镜像,须要为 Docker daemon 配置镜像减速,参考阿里云镜像服务--cpus=2: 为minikube虚拟机调配CPU核数--memory=2048mb: 为minikube虚拟机分配内存数--kubernetes-version=***: minikube 虚拟机将应用的 kubernetes 版本当你执行minkube start会呈现这个谬误,大略意思是须要加个 --driver=none的参数 谬误一:The "docker" driver should not be used with root privileges.If you are running minikube within a VM, consider using --driver=none:https://minikube.sigs.k8s.io/... X Exiting due to DRV_AS_ROOT: The "docker" driver should not be used with root privileges.加了参数当前那就恐怖了 ...

September 13, 2020 · 2 min · jiezi

关于k8s:Kubernetes世界中的虚拟机

KubeCon + CloudNativeCon资助客座文章来自红帽云平台产品治理Peter Lauterbach 加入KubeCon的人晓得,容器技术会持续存在。事实上,“Gartner预测,到2022年,超过75%的寰球组织将在生产中运行容器化应用程序,这比2019年的不到30%有了显著增长”。及时提交应用程序,使咱们放弃竞争力,并与咱们的客户根底相干。为了做到这一点,许多公司都采纳了容器框架,以提高效率和速度。适应新技术并不总是那么容易。有些应用程序可能须要应用遗留技术,或者须要投入大量工夫和精力来构建新的技术。咱们如何解决那些须要应用虚拟机的应用程序,而不使虚拟化和容器技术的治理复杂化?欢送来到KubeVirt。 KubeVirt我的项目从新构想了Kubernetes世界中的虚拟机。能够创立虚拟机,或者将其从遗留框架迁徙到kubernetes优先的治理范例中。开发人员能够应用他们现有的Kubernetes工具集来原生地治理VM,或者将这些工作负载转换为容器。这为组织和反对开发团队提供了空间,以便在对其业务有意义的事实工夫线上更新应用程序。 听起来乏味吗?兴许有点太神奇了?上面是在Kubernetes中开始试验虚拟机的一些办法。 从繁多的管制立体反对遗留架构 KubeVirt的美好之处在于,它容许开发团队将现有的应用程序从新设计为云原生、容器优先的部署,而不是让开发人员承当在Kubernetes上用不可能的工夫线从新构建所有内容的累赘。通过KubeVirt中的繁多管制立体简化了VM和容器的治理。基于获奖的KVM技术,KubeVirt提供了成熟的虚拟化能力和性能,并间接带来Kubernetes的益处。 应用程序现代化 在努力实现DevOps或云原生应用程序架构时,有三个要害思考因素:业务需要、技术需要和迁徙策略。 业务需要:现代化可能从Kubernetes性能中获益的工作负载,同时在虚拟机上放弃更传统的个性。利用这个机会来确定你将来3-5年的业务需要,并理解你从明天开始要做什么。你们都应用虚拟机了吗?你对DevOps或云原生感兴趣吗?如果你对Kubernetes感兴趣,然而你晓得虚拟机上存在依赖关系,那么能够在转换过程中包含KubeVirt作为测试选项。技术思考:当你晓得Kubernetes将呈现在你的将来,请思考KubeVirt的技术能力。Kubernetes提供了与传统虚拟机不同的治理范例。调整大小、备份甚至工作负载认证的策略可能与你当初所经验的不同。KubeVirt的次要长处之一是,通过将虚拟机和容器放在繁多管制立体下,能够简化治理工具集的数量。KubeVirt是一个动静我的项目--如果这个平台明天不能100%满足你的需要,不要放弃它。迁徙策略:包含文件和web服务器、.NET应用程序、Java和企业数据库在内的工作负载是从传统VM迁徙到Kubernetes的现实抉择。从这样的VM开始,在转移到更简单的工作负载之前,你能够试验最简略的设置。在这里,你能够将虚拟机导入KubeVirt,并利用最佳实际来进行VM镜像解决或Windows装置。依照本人的节奏倒退 在Kubernetes中开始应用VM是很容易(KubeVirt能够供下载并作为操作器部署),而且倒退起来也很简略和无效。如果你筹备应用KubeVirt,那么能够启动一个新的虚拟机,或者将现有的VM迁徙到KubeVirt。扩大集群就像退出一个节点一样简略,并且齐全通过操作器执行。反对的虚拟机数量没有限度,而且虚拟机具备传统虚拟机环境中常见的雷同数据持久性。当你对该平台越来越相熟,能够向上扩大加强VM并最终取代传统的虚拟化。 KubeVirt被世界各地的客户和社区成员大规模利用和部署。OpenShift Virtualization当初是Red Hat OpenShift容器平台齐全反对的个性。OpenShift Virtualization是第一个基于KubeVirt的齐全受反对的产品,打消了传统应用程序栈中常常存在的操作和开发之间的竖井。 想理解更多对于KubeVirt的信息,请退出咱们的论坛、Slack(Kubernetes的#virtualization频道)、Twitter,或者退出KubeVirt社区。 点击浏览网站原文。 CNCF (Cloud Native Computing Foundation)成立于2015年12月,隶属于Linux  Foundation,是非营利性组织。 CNCF(云原生计算基金会)致力于培养和保护一个厂商中立的开源生态系统,来推广云原生技术。咱们通过将最前沿的模式民主化,让这些翻新为公众所用。扫描二维码关注CNCF微信公众号。

September 10, 2020 · 1 min · jiezi

关于k8s:使用Kubernetes来构建克服新的建筑成本

客座文章之前由Brad Ascar,高级解决方案架构师,在Carbon Relay博客上发表 市场数据显示,容器化的采纳是如许迅速,特地是Kubernetes在企业中的增长。例如,CNCF最近的一项考察显示,84%的企业IT受访者示意,他们在生产中运行容器,其中大部分(78%)援用Kubernetes作为编排零碎。 换句话说,容器和Kubernetes曾经成为支流。 这意味着许多企业IT和DevOps团队都在应用这项相当新的技术(它只有6年的历史),作为他们为云原生世界重建遗留IT环境的要害局部。 有很多新的IT“修建”是由绝对缺乏经验的工作人员应用新资料和新技术建造的。 然而,正如每一个修建监理和贸易人员都晓得的那样,解决新“货色”天然会带来一些问题和挑战。 这些Kubernetes构建人员遇到的一些常见问题是什么?以下是咱们在该畛域看到的或在行业内听到的一些重点。 新技术,缺乏经验 Kubernetes的新面孔,加上它的迅速遍及,导致了技术上的差距。在这项技术上有丰盛教训的人很难找到和招聘,雇佣老本也很高。依据Enterprise Project,Kubernetes的工作在全国的平均工资靠近14.5万美元。 因而,一些企业急于向前倒退,把那些原本很有成就的人放在下面,认为他们会解决。这就像让一个木匠学徒来搭建整个房子。这是一种蹩脚的开始形式,即便最终取得了可承受的后果,在此过程中也必定会呈现问题。 生疏景观 Kubernetes承诺在更少的基础设施和更低的老本下实现更大的业务敏捷性和响应能力。通常从一个应用程序开始,企业团队面临将其转换为齐全不同货色的艰巨工作。在许多状况下,它们采纳一个具备单体设计的应用程序(在事后配置的数据中心的专用硬件上的虚拟机中运行的对立堆栈),并将其合成为微服务汇合,通过云从一系列不同的起源进行配置。 尽管新的微服务和容器化办法很简单,但大多数企业团队都有能力建设一个Kubernetes集群,并在其上运行一个应用程序。让这个应用程序牢靠地运行,而后优化,这才是真正的挑战。 适度配置 当初很多公司都在产生这样的事件。他们的团队曾经应用Kubernetes,建设集群,他们曾经将大型利用分解成许多小块,这些小块是他们从云中的不同起源收集来的。他们的第一个K8s应用程序曾经启动并运行。而后,他们试图通过更改设置来对其进行一些调整,而后,砰的一声!利用解体。或者,它们没有更改任何默认值,而较大的负载或零碎上的其余压力导致系统呈现故障。 尽管他们不晓得为什么这个应用程序在1g的状况下会解体,但他们意识到在1.5g的状况下解体的几率会小一些。所以,他们尝试了2g,它在大部分工夫仿佛运行失常。然而“ok”并不能解决问题。为了升高应用程序的危险,防止停机和凌晨3点的紧急呼叫,他们将配置晋升到4g。 后果呢?一个应用程序,如果正确配置,可能在最高250mb的状况下牢靠地运行,则有375%的过载。当第二个、第三个、第四个或第100个应用程序被容器化时,同样的适度配置产生时,问题随之而来。在某个时候,零碎会解体,应用程序会解体,危险会变成理论的操作和名誉侵害。当云资源耗费的指数级增长反映在云服务提供商的每月账单上时,这种挫伤就更大了。 尽管这些团队可能缩小了必须购买和治理的基础设施的数量,并进步了业务敏捷性,但其老本往往是其老式本地硬件和vm老本的好几倍。 玩“打地鼠”式的设置 在Kubernetes清单中,IT团队能够操作两个次要的设置,并且只针对两种资源类型。有一些针对资源申请和资源限度的设置,它们利用于CPU和内存资源。再加上replicaset和主动缩放选项等概念,就会有许多可挪动的局部。应用程序是scale-up,还是scale-out?哪种形式更经济实惠? 初始设置可能在一段时间内工作良好,即便它们在谬误的中央开始,并且当初正在测量谬误的事件,或谬误的形式运行正确的事件。然而,随着程度扩大部署和新的集群上线,以及具备十分不同行为的新应用程序被退出其中,事件可能会出错。因为初始设置不再无效,IT团队心愿调整它们。 这就是“打地鼠”游戏的开始。不足对设置更改的影响的可见性,将这个过程变成了危险的猜想。兴许更重要的是,它耗费了开发人员低廉的工夫。 应用程序参数使事件进一步复杂化 只管针对Kubernetes的部署设计显著不同,应用程序依然有可调参数,团队能够对其进行批改和更改。例如,对于一个简略的数据库,团队能够设置内存和页面缓存资源的级别、数据在写入磁盘之前在内存中存在多长时间的时间段,以及容许运行多少个正本。 另一个例子是Java应用程序,其中有许多JVM设置须要设置和调优,比方堆大小和垃圾收集参数,这些设置对性能有很大影响。 应用程序可能成为“乐音街坊”,并开始影响其余应用程序的性能。在多层环境中部署时,在第一层调优参数通常绝对容易,危险也低,但在第二层和第三层,难度和危险显著减少。 简而言之,Kubernetes中容许的最小设置,加上应用程序“堆栈”的不同层上不同的可调参数,使得实现Kubernetes应用程序的性能和老本十分艰难。 总结 这并不是说IT团队最终不能失去他们须要的答案。而是说这是一项艰难、乏味、有危险的工作,而且他们须要疾速解决变动。因而,就像由木匠、水管工和电工组成的建筑工人一样,这些企业团队所从事的工作须要艰辛、乏味、有时还有危险。他们正在做的IT工作相当于建造一个新的构造--挪动和筹备资料,初步确定新构造,并实现最初的工作。 然而,有一些新的、聪慧的办法能够确保你的IT构建人员团队防止上述列出的缺点。应用这些新办法,当他们看到本人曾经胜利建设的货色时,肯定会微笑。咱们将在下一篇文章中探讨这些新办法。请持续关注。 点击浏览网站原文。 CNCF (Cloud Native Computing Foundation)成立于2015年12月,隶属于Linux  Foundation,是非营利性组织。 CNCF(云原生计算基金会)致力于培养和保护一个厂商中立的开源生态系统,来推广云原生技术。咱们通过将最前沿的模式民主化,让这些翻新为公众所用。扫描二维码关注CNCF微信公众号。

September 9, 2020 · 1 min · jiezi

关于k8s:Kubernetes引入结构化日志

作者:Marek Siarkowicz(谷歌)、Nathan Beach(谷歌) 日志是可察看性的一个根本方面,也是调试的一个要害工具。然而Kubernetes日志传统上是非结构化字符串,这使得任何主动解析都很艰难,任何上游解决、剖析或查问都很难牢靠地实现。 在Kubernetes 1.19中,咱们减少了对结构化日志的反对,它原生反对(键、值)对和对象援用。咱们还更新了许多日志调用,这样在一个典型的部署中超过99%的日志量当初都迁徙到了结构化格局。 为了放弃向后兼容性,结构化日志仍将输入为字符串,其中字符串蕴含“key”=“value”对的示意。从1.19的alpha开始,日志也能够应用--logging-format=json标记以JSON格局输入。 应用结构化日志 咱们向klog库增加了两个新办法:InfoS和ErrorS。例如,以下信息的调用: klog.InfoS("Pod status updated", "pod", klog.KObj(pod), "status", status)将导致以下日志: I1025 00:15:15.525108       1 controller_utils.go:116] "Pod status updated" pod="kube-system/kubedns" status="ready"或者,如果设置了--logging-format=json标记,则会产生如下输入: { "ts": 1580306777.04728, "msg": "Pod status updated", "pod": { "name": "coredns", "namespace": "kube-system" }, "status": "ready"}这意味着上游的日志工具能够很容易地获取结构化日志数据,而不是应用正则表达式(regex)来解析非结构化字符串。这也使得解决日志更容易,查问日志更强壮,剖析日志更快。 应用结构化日志,对Kubernetes对象的所有援用都以雷同的形式进行结构化,因而你能够过滤援用特定pod的输入和日志条目。你还能够找到一些日志,这些日志批示调度器如何调度pod、如何创立pod、pod的运行状况探测以及pod生命周期中的所有其余更改。 假如你正在用pod调试一个问题。应用结构化日志,你能够筛选到仅援用感兴趣的pod的那些日志条目,而不须要扫描可能数以千计的日志行来查找相干的日志。 结构化日志不仅在手动调试问题时更有用,而且还反对更丰盛的个性,如日志中的主动模式识别或日志和跟踪数据的更严密的相关性。 最初,结构化日志能够帮忙升高日志的存储老本,因为大多数存储系统压缩结构化的key=value数据比压缩非结构化的字符串更无效。 来参加 尽管在一个典型的部署中,咱们曾经按日志量更新了超过99%的日志条目,但依然有数千个日志须要更新。抉择一个你想要改良的文件或目录,并将现有的日志调用迁徙到应用结构化日志。这是对Kubernetes做出第一份奉献的一种平凡而简略的形式! 点击浏览网站原文。 CNCF (Cloud Native Computing Foundation)成立于2015年12月,隶属于Linux  Foundation,是非营利性组织。 CNCF(云原生计算基金会)致力于培养和保护一个厂商中立的开源生态系统,来推广云原生技术。咱们通过将最前沿的模式民主化,让这些翻新为公众所用。扫描二维码关注CNCF微信公众号。

September 8, 2020 · 1 min · jiezi

关于k8s:警告有用的警告|让Kubernetes的使用越来越容易

作者:Jordan Liggitt(谷歌) 作为Kubernetes的维护者,咱们始终在寻找在放弃兼容性的同时进步可用性的办法。在开发个性、分类bug和答复反对问题的过程中,咱们积攒了有助于Kubernetes用户理解的信息。在过来,信息的共享仅限于公布阐明、布告电子邮件、文档和博客文章等内部办法。除非有人晓得该信息并设法找到它,否则他们不会从中受害。 在Kubernetes v1.19中,咱们增加了一个个性,容许Kubernetes API服务器向API客户机发送正告。正告是应用规范的Warning响应头发送的,因而它不会以任何形式更改状态代码或响应体。这容许服务器发送正告,任何API客户端都能够轻松读取,同时放弃与以前的客户端版本兼容。 正告在kubectl v1.19+的stderr输入和k8s.io/client-go客户端库v0.19.0+的日志输入。k8s.io/client-go的设定能够按过程或按客户端笼罩。 弃用的正告 咱们应用这个新性能的第一种形式是,对应用已弃用的API(deprecated API)发送正告。 Kubernetes是一个疾速倒退的大型项目。即便对于全职从事我的项目的人来说,跟上每个版本中的变动也是一件令人生畏的事件。一种重要的扭转是API的弃用。随着Kubernetes中的API降级到GA版本,预公布的API版本将被弃用并最终被删除。 即便有一个缩短的弃用期,并且在公布阐明中蕴含了弃用,它们依然很难跟踪。在弃用期间,预公布API依然无效,容许多个版本转换为稳固的API版本。然而,咱们发现,用户通常甚至没有意识到他们所依赖的API版本曾经弃用,直到他们降级到不再提供它的版本。 从v1.19开始,每当向弃用的REST API发出请求时,都会在API响应的同时返回一个正告。此正告包含无关API将不再可用的版本的详细信息,以及替换的API版本。 因为正告来自服务器,在客户端被拦挡,所以它实用于所有的kubectl命令,包含像kubectl apply这样的高级命令,和像kubectl get --raw这样的低级命令: 这有助于受弃用影响的人晓得他们收回的申请已被弃用,他们须要多长时间来解决这个问题,以及他们应该应用什么API来代替。当用户利用本人没有创立的清单时,这尤其有用,这样他们就有工夫分割作者,要求更新版本。 咱们还意识到,应用已弃用API的人通常不是负责降级集群的同一个人,因而咱们增加了两个面向管理员的工具,以帮忙跟踪已弃用API的应用状况,并确定何时降级是平安的。 指标 从Kubernetes v1.19开始,当向已弃用的REST API端点发出请求时,在kube-apiserver过程中将apiserver_requested_deprecated_apis度量指标设置为1。此指标具备API group、version、resource、subresource的标签,以及一个removed_version标签,该标签批示不再提供API的Kubernetes版本。 这是一个应用kubectl、prom2json和jq的示例查问,用于确定API服务器的以后实例申请了哪些弃用的API: kubectl get --raw /metrics | prom2json | jq ' .[] | select(.name=="apiserver_requested_deprecated_apis").metrics[].labels'输入: { "group": "extensions", "removed_release": "1.22", "resource": "ingresses", "subresource": "", "version": "v1beta1"}{ "group": "rbac.authorization.k8s.io", "removed_release": "1.22", "resource": "clusterroles", "subresource": "", "version": "v1beta1"}这显示了弃用的extensions/v1beta1 Ingress和rbac.authorization.k8s.io/v1beta1 ClusterRole API在此服务器上被申请,将在v1.22中被删除。 咱们能够将这些信息与apiserver_request_total指标连接起来,以取得对于向这些API收回的申请的更多细节: kubectl get --raw /metrics | prom2json | jq ' # set $deprecated to a list of deprecated APIs [ .[] | select(.name=="apiserver_requested_deprecated_apis").metrics[].labels | {group,version,resource} ] as $deprecated | # select apiserver_request_total metrics which are deprecated .[] | select(.name=="apiserver_request_total").metrics[] | select(.labels | {group,version,resource} as $key | $deprecated | index($key))'输入: ...

September 8, 2020 · 2 min · jiezi

关于k8s:Kubernetes如何自动检测和处理弃用的API

作者:Stepan Stipl,DoiT International高级云架构师。客座文章最后在DoiT International博客上发表。 随着Kubernetes 1.16可用一段时间,并开始在许多托管Kubernetes平台上迟缓推出,你可能据说过API弃用(deprecation)。尽管解决起来相当简略,然而如果无人参加,这种更改可能会重大地中断你的服务。 API弃用是什么? 随着Kubernetes的个性集的倒退,API也必须倒退以反对这种变动。有一些规定旨在保障兼容性和稳定性。这种状况不会在每个版本中都产生,但最终,你将不得不应用新的API版本和格局,因为旧的API将不再受反对。 为什么这对于1.16版本如此重要? 在最近几个K8s版本中保留了一些弃用的API,最终在Kubernetes 1.16版本中被齐全删除。即以下API组和版本: Deployment — extensions/v1beta1, apps/v1beta1 and apps/v1beta2NetworkPolicy — extensions/v1beta1PodSecurityPolicy — extensions/v1beta1DaemonSet — extensions/v1beta1 and apps/v1beta2StatefulSet — apps/v1beta1 and apps/v1beta2ReplicaSet — extensions/v1beta1, apps/v1beta1 and apps/v1beta2如果尝试在1.16中应用其中之一创立资源,操作将会失败。 如何查看我是否受到影响? 你能够手动遍历所有清单,但这可能相当耗时。如果有多个团队部署到集群中,或者在一个中央没有以后的所有清单,那么很容易失落一些清单,并且可能十分不理论。这就是kubent(Kube-No-Trouble)来帮忙的中央。 问题是什么? 用于创立给定资源的API版本的信息通常是不容易找到,因为资源总是在外部转换为首选存储版本并存储在首选存储版本中。然而。如果你应用kubectl或Helm来部署资源,原始清单也存储在集群中,咱们能够利用它。如果是kubectl,则模式为kubectl.kubernetes.io/last-applied-configuration正文;如果是Helm,则模式为ConfigMap或Secret。 如何解决弃用产生的问题 最简略的办法是装置: sh -c "$(curl -sSL 'https://git.io/install-kubent')"这将把kubent的最新版本装置到/usr/local/bin中。 (如果你和我一样,不置信他人在博客文章中公布的随机脚本,请下载针对你的平台的最新版本,而后解压缩到你喜爱的任何中央。) 配置kubectl的以后上下文,以指向你想要检查和运行kubent工具的集群: 图1:kubent运行的示例输入 Kubent将连贯到你的集群,检索所有可能受到影响的资源,扫描并打印那些受到影响的资源的摘要。 你还能够应用-f json标记来取得JSON格局的输入,这更适宜让你将其集成到你的CI/CD流水线中或进一步处理结果。对于可用配置选项的更多细节在doitintl/kube-no-trouble仓库的README文件中形容。 我应该如何解决检测到的资源? 在某些状况下,这就像扭转manifest中的apiVersion一样简略,但在其余状况下,构造可能曾经扭转,须要调整。另外,要留神,版本之间有很多默认值会发生变化(对于这方面的好文章是David Schweikert的Kubernetes 1.16 API deprecations and changed defaults),因而,仅更改apiVersion并利用雷同的清单,就会失去不同的后果。例如,StatefulSet的updateStrategy.type从OnDelete更改为RollingUpdate,导致了十分不同的行为。 以前应用的kubectl convert命令现已弃用,可能不能依据后面提到的默认值正确地转换资源。 最好的办法可能是简略地利用资源(如果你应用kubent检测到它们,那么你曾经有了这些资源)并从API检索新版本。这将确保资源被正确地转换为新版本。你可能曾经留神到,kubectl在某种程度上不确定地返回的版本。要申请一个特定的API版本,应用残缺的模式: kubectl get ingress.v1beta1.extensions -o yaml欢送反馈! ...

September 2, 2020 · 1 min · jiezi

关于k8s:Kubernetes从Beta前进避免永久Beta

作者:Tim Bannister,The Scale Factory 在Kubernetes中,个性遵循一个已定义的生命周期。首先,作为一个感兴趣的开发人员的一瞬。兴许,在网上的探讨中,在相当于咖啡餐巾的网上画上草图。这种毛糙的工作通常会变成KEP(Kubernetes加强倡议,Kubernetes Enhancement Proposal),而后通常会转换成代码。 对于Kubernetes v1.20及当前版本,咱们的重点是帮忙这些代码过渡到稳固的个性。 我提到的生命周期运行如下: Alpha→Beta→GA 通常,alpha个性在默认状况下是不启用的。你通过设置性能门(feature gate)来关上它们;通常,通过在应用该个性的每个组件上设置一个命令行标记。 (如果你通过托管服务 - 如AKS、EKS、GKE等 - 应用Kubernetes,那么运行该服务的供应商可能曾经决定为你启用哪些个性了)。 将一个现有的、alpha的个性转化为beta阶段是一个明确的过程。这一点很重要,因为测试版(beta)个性是默认启用的,个性标记依然存在,所以集群操作人员能够抉择不启用。 一套相似但更彻底的分级规范管制着向GA(general availability)的过渡,也被称为“稳固(stable)”。GA个性是Kubernetes的一部分,并承诺在以后次要版本中保留它们。 默认测试版性能能够让Kubernetes和它的贡献者取得有价值的真实世界的反馈。然而,激励机制却不匹配。一旦一个个性被默认启用,人们就会应用它。即便有一些细节须要解决,Kubernetes的REST API和常规的工作形式意味着任何将来稳固的API都将与最新的beta API兼容:当一个beta个性降级到GA时,API对象不会进行工作。 特地是对于API及其资源,将性能从beta转移到GA的动机远不如从alpha转移到beta。想要某个特定个性的供应商有很好的理由帮忙代码达到默认启用个性的水平,除此之外,这个过程就不那么清晰了。 KEP跟踪的不仅仅是代码改良。实质上,任何须要与更宽泛的社区进行交换的货色都值得应用KEP。也就是说,大多数KEP笼罩了Kubernetes的个性(以及实现这些个性的代码)。 你可能晓得Ingress在Kubernetes曾经有一段时间了,但你是否意识到它实际上在2015年就开始进入beta了?为了帮忙推动事件向前,Kubernetes的架构特地兴趣小组(SIG)有一个新的办法。 防止永恒测试版 对于Kubernetes REST API来说,当一个新个性的API达到beta时,就开始倒计时了。测试版API当初有九个月的工夫: 达到GA,并弃用beta,或领有一个新的测试版(并弃用之前的测试版)。须要明确的是,此时只有REST API会受到影响。例如,APIListChunking是一个beta个性,但它自身不是REST API。目前还没有打算主动弃用APIListChunking,或任何其余非REST API的个性。 如果REST API达到了9个月的倒计时,那么下一个Kubernetes版本将会弃用该API版本。在Kubernetes 9个月后公布的第一个测试版之后,REST API不能抉择持续放弃测试版。 这对你意味着什么 如果你正在应用Kubernetes,那么你很有可能正在应用beta个性。就像我说的,有很多。和Ingress一样,你可能正在应用CronJob,或PodSecurityPolicy,或其余。更大的可能性是,你运行在一个至多启用了一个测试版个性的管制立体上。 如果你正在应用或生成应用像Ingress这样的beta API的Kubernetes清单,则须要打算批改它们。以后的API将依照打算(我后面提到的9个月)被弃用,9个月后那些弃用的API将被删除。此时,为了与Kubernetes放弃同步,你应该曾经进行了迁徙。 这对Kubernetes的贡献者意味着什么 这里的动机仿佛很分明:让个性稳固。保障beta个性将会被废除,这是一个很大的激励,因而想要该个性的人们会持续致力,直到该个性的代码、文档和测试曾经筹备好达到稳固,并失去Kubernetes在理论应用中公布的证据的反对。 这对生态系统意味着什么 在我看来,这些看似严格的措施是很有意义的,而且对Kubernetes也有益处。通过一种实用于所有不同非凡趣味组(SIG)的规定来弃用现有API,有助于防止停滞并激励修复。 假如一个API达到了beta,而后理论教训表明它是不正确的——从根本上说,这个API有缺点。随着9个月的倒计时,相干人员有了办法和理由来批改和公布解决问题案例的API。欢送任何心愿应用这个已被弃用的API的人应用它 - Kubernetes是开源的 - 然而他们的需要不用妨碍这个个性的倒退。 点击浏览网站原文。 CNCF (Cloud Native Computing Foundation)成立于2015年12月,隶属于Linux  Foundation,是非营利性组织。 CNCF(云原生计算基金会)致力于培养和保护一个厂商中立的开源生态系统,来推广云原生技术。咱们通过将最前沿的模式民主化,让这些翻新为公众所用。扫描二维码关注CNCF微信公众号。

September 2, 2020 · 1 min · jiezi

关于k8s:K8S集群学习笔记整理三

参考文章主参考:《Centos7.6部署k8s v1.16.4高可用集群(主备模式)》《应用kubeadm在Centos8上部署kubernetes1.18》《应用kubeadm部署k8s集群[v1.18.0]》 1、环境规划a. 主机布局# 主机名 Centos版本 ip docker version flannel version Keepalived version 主机配置 备注# master01 7-8.2003 192.168.1.121 19.03.9 v0.11.0 v1.3.5 2C2G control plane# master02 7-8.2003 192.168.1.122 19.03.9 v0.11.0 v1.3.5 2C2G control plane# master03 7-8.2003 192.168.1.123 19.03.9 v0.11.0 v1.3.5 2C2G control plane# work01 7-8.2003 192.168.1.131 19.03.9 / / 2C2G worker nodes# work02 7-8.2003 192.168.1.132 19.03.9 / / 2C2G worker nodes# work03 7-8.2003 192.168.1.133 19.03.9 / / 2C2G worker nodes# VIP 7-8.2003 192.168.1.200 19.03.9 v0.11.0 v1.3.5 2C2G 在control plane上浮动# client 7-8.2003 192.168.1.201 / / / 2C2G client# 共有7台服务器,3台control plane【1台VirtualPC】,3台work,1台client不动。# 试验机-16G内存:集群节点全副退出master1后,根本内存占用99%,kubectl get nodes查问常常回绝,后内存改为 1200b. vagrant 筹备centos7筹备略。 ...

August 29, 2020 · 5 min · jiezi

关于k8s:为什么使用OPA而不是原生的Pod安全策略

客座文章之前由Mohamed Ahmed在Magalix博客上发表 在本文中,咱们将演示如何应用OPA执行最细粒度的安全策略。请留神,本文是一个系列的一部分,咱们将基于“OPA作为代码介绍”和“集成OPA到Kubernetes”中取得的常识进行。如果你还没有这样做,请浏览本系列中已发表的文章。 你可能曾经相熟Pod安全策略,能够在其中对Pod利用十分特定的安全控制。例如,应用Linux内核性能,应用主机命名空间、网络、端口或文件系统,以及其余许多性能。应用OPA,你还能够对pods施加相似的管制,在本实验室中,咱们将创立一个OPA策略,不容许在pods中创立有特权的容器。特权容器对主机的拜访级别比非特权容器高。 为什么应用OPA而不是原生的Pod安全策略? 应用Pod安全策略来执行咱们的安全策略并没有什么问题。然而,依据定义,PSP只能利用于pods。它们不能解决其余Kubernetes资源,如Ingresses、Deployments、Services等。OPA的弱小之处在于它能够利用于任何Kubernetes资源。OPA作为一个许可控制器部署到Kubernetes,它拦挡发送到API服务器的API调用,并验证和/或批改它们。相应地,你能够有一个对立的OPA策略,实用于零碎的不同组件,而不仅仅是pods。例如,有一种策略,强制用户在其服务中应用公司的域,并确保用户只从公司的镜像存储库中提取镜像。请留神,咱们应用的OPA是应用kube-mgmt部署的,而不是OPA Gatekeeper。 Rego的策略代码 在本文中,咱们假如你曾经相熟了OPA和Rego语言。咱们还假如你有一个正在运行的Kubernetes集群,该集群部署了OPA和kube-mgmt容器。无关装置阐明,请参阅咱们的前一篇文章。咱们的no-priv-pod.rego文件如下所示: package kubernetes.admissiondeny[msg] { c := input_containers[_] c.securityContext.privileged msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext])}input_containers[c] { c := input.request.object.spec.containers[_]}input_containers[c] { c := input.request.object.spec.initContainers[_]}让咱们简要地浏览一下这个文件: 第1行:蕴含package。留神,你必须应用kubernetes.admission让政策工作。第2行:Deny是默认对象,它将蕴含咱们须要执行的策略。如果所蕴含的代码计算结果为true,则将违反策略。第3行:咱们定义了一个变量,它将包容pod中的所有容器,并从稍后定义的input_containers[c]接管值。第4行:如果pod蕴含“privileged”属性,则该语句为true。第5行:当用户尝试运行特权容器时显示给他们的音讯。它包含容器名称和违规的平安上下文。第7-9行:input_containers[c]函数从申请对象中提取容器。留神,应用了_字符来遍历数组中的所有容器。在Rego中,你不须要定义循环—下划线字符将主动为你实现此操作。第10-12行:咱们再次为init容器定义函数。请留神,在Rego中,能够屡次定义同一个函数。这样做是为了克服Rego函数中不能返回多个输入的限度。当调用函数名时,将执行两个函数,并应用AND操作符组合输入。因而,在咱们的例子中,在一个或多个地位中存在一个有特权的容器将违反策略。部署策略 OPA会在opa命名空间的ConfigMaps中找到它的策略。要将咱们的代码利用到ConfigMap中,咱们运行以下命令: kubectl create configmap no-priv-pods --from-file=no-priv-pod.regokube-mgmt边车(sidecar)容器在opa命名空间中继续监督API服务器,以便你只需创立ConfigMap就能够部署策略。 运行策略 让咱们通过尝试部署一个特权容器来确保咱们的策略是无效的: kubectl -n default apply -f - <<EOTapiVersion: v1kind: Podmetadata: name: nginx-privileged labels: app: nginx-privilegedspec: containers: - name: nginx image: nginx securityContext: privileged: true #falseEOTError from server (Privileged container is not allowed: nginx, securityContext: {"privileged": true}): error when creating "STDIN": admission webhook "validating-webhook.openpolicyagent.org" denied the request: Privileged container is not allowed: nginx, securityContext: {"privileged": true}请留神,咱们无意将pod部署到默认命名空间,因为咱们的admission webhook将疏忽在opa命名空间或kube-system中创立的任何资源。 ...

August 28, 2020 · 1 min · jiezi

关于k8s:探究K8S-v119-GA的Seccomp

什么是Seccomp?Seccomp(全称:secure computing mode)在2.6.12版本(2005年3月8日)中引入linux内核,是一种限度零碎调用的平安机制。在严格模式下,将过程可用的零碎调用限度为四种:read,write,exit,sigreturn,其余的零碎调用都会杀死过程。过滤模式下,能够指定容许那些零碎调用,Seccomp进行过滤的形式是基于应用SECCOMP_MODE_FILTER模式的BPF过滤器,并且零碎调用过滤的形式与对数据包的过滤形式雷同。例如,您可能心愿为过程提供CAP_NET_ADMIN性能,但通过阻塞accept和accept4零碎调用的形式不容许它承受套接字上的连贯。 从linux/seccomp.h 的内核源代码中看,seccomp_data构造的样子如下: struct seccomp_data { int nr; __u32 arch; __u64 instruction_pointer; __u64 args[6]; };通过该构造能够看出,咱们能够基于syscall,基于其参数或基于它们的组合进行过滤。 kubernetes中的seccompSeccomp在Kubernetes 1.3版本中作为Alpha性能引入,应用PodSecurityPolicy上的正文将Seccomp配置文件利用于所需的Pod。 例如咱们要将一个seccomp profile 设置到某个pod范畴: annotations: seccomp.security.alpha.kubernetes.io/pod: "localhost/profile.json"或者咱们设置到容器范畴: annotations: container.security.alpha.kubernetes.io/<container-name>: "localhost/profile.json"在1.19版中,Seccomp 性能 GA,将新的seccompProfile字段增加到pod和容器的securityContext对象中。 apiVersion: v1kind: Podmetadata: name: audit-pod labels: app: audit-podspec: securityContext: seccompProfile: type: RuntimeDefault containers: - name: test-container image: hashicorp/http-echo:0.2.3 args: - "-text=just made some syscalls!" securityContext: allowPrivilegeEscalation: false此处咱们能够看到咱们应用了RuntimeDefault, 该type是k8s默认的容器运行时profile。 此处可能的值为: Unconfined - 如果没有其余抉择,Seccomp不会利用于容器过程(这是Kubernetes中的默认设置)。RuntimeDefault - 应用默认的容器运行时配置文件。Localhost - 指定自定有的profile文件。当type 为该值时,此时必须指定localhostProfile字段的值。比方: ...

August 28, 2020 · 1 min · jiezi

关于k8s:如何基于K8s构建下一代DevOps平台

简介: OAM是阿里巴巴与微软联合推出的凋谢利用模型,旨在解耦利用研发、利用运维与基础设施人员在利用生命周期中各自的关注点,清晰责任与界线,聚焦本身业务,同时又仍然能严密合作。以后云原生DevOps体系现状如何?面临哪些挑战?如何通过OAM解决云原生DevOps场景下的诸多问题?云原生开发利用模型OAM(Open Application Model)社区核心成员孙健波将为大家一一解答,并分享如何基于OAM和Kubernetes打造有限能力的下一代DevOps平台。 一 什么是DevOps?为什么基于Kubernetes构建?2009年举办了第一届DevOpsDays大会,DevOps名字被首次提出。到2010年,DevOps的概念越来越火,出了What is DevOps的文章,解说了DevOps的概念,方法论及配套的工具。简略来说,研发工程师须要和运维工程师深度的单干,同时通过一系列工具保障研发更加顺畅,从而更容易的接触生产环境。到2013年,Docker呈现了,工程师能够第一次到软件生产环境中定义,通过Docker image实现单机软件的交付和散发。此时DevOps开始缓缓落地。2015年开始,DevOps相干的工具越来越多,资源利用率呈现了一些问题,CNCF的成立使得DevOps的实际往Kubernetes上走。 阿里在Kubernetes上的实际也获得了十分好的成绩。在规模方面,阿里外部集成了数十个节点能够达到上万的集群,同时具备高性能和平安个性,秒级扩容,神龙+平安容器。具备极致的弹性,分钟级拆解私有云计算资源,有限资源池。另一方面,Kubernetes社区曾经具备十分丰盛的DevOps生态根底性能,包含镜像托管、CICD流水线、工作编排、公布策略、镜像打包、散发、丰盛的利用运行时的负载撑持、丰盛弹性和利用扩容能力。 为什么阿里基于Kubernetes构建DevOps平台? 1)阿里基于Kubernetes的有限资源池与基础设施能力 大规模 – 单集群最高可达10000节点、百万Pod高性能 – 秒级扩容,智能伸缩,神龙 + 平安容器极致弹性 – 分钟级拆解私有云计算资源,有限资源池2)社区围绕Kubernetes曾经具备丰盛的DevOps生态根底性能 源码到容器镜像仓库,Kubernetes是容器平台事实标准:Github/DockerHubCI/CD流水线、工作编排、公布策略:Argo/Teckton/Spinnaker/Jenkins-X/Flagger镜像打包、散发:Helm/CNAB丰盛的利用运行负载撑持:Deployment(无状态)/StatefulSet(有状态)/OpenKruise(原生有状态加强)丰盛的弹性和利用扩缩容能力:HPA/KEDA二 基于Kubernetes的DevOps平台新挑战下图展现了一个云原生下的DevOps流水线的典型流程。首先是代码的开发,代码托管到Github,再接入单元测试的工具Jenkins,此时根本研发已实现。再接着到镜像的构建,波及到配置、编排等。云原生中能够用HELM打包利用。打包好的利用部署到各个环境中。但整个过程中会面临很多挑战。首先,在不同的环境须要不同的运维能力。 其次,配置的过程中要创立云上数据库,须要另外关上一个控制台来创立数据库。还须要配置负载平衡。在利用启动当前还须要配置额定的性能,包含日志、策略、平安防护等等。能够发现,云资源和DevOps平台体验是割裂的,外面充斥着借助内部平台创立的过程。这对老手来说是十分苦楚的。 挑战一:云资源与 DevOps 平台体验割裂DevOps流程中充斥着大量须要内部平台创立的过程: 挑战二:研发、运维、基础设施关注点耦合下图是罕用的K8s的YAML配置文件,大家常常吐槽这个配置文件很简单。简略来说YAML配置文件能够分为三大块,一块是运维比较关心的配置,包含实例数,策略和公布。第二块是研发关怀的,波及到镜像、端口号等。第三块是基础设施工程师看得懂的,如调度策略等。K8s的配置文件中将方方面面的信息都耦合在一起,这对K8s工程师来说是非常适合的,然而对利用侧的终端工程师而言,有很多不须要关怀的配置指标。 DevOps流程中不足对“利用”这个概念的形容K8s 的 YAML文件的定位并不是终端用户挑战三:平台的自定义封装,简略却能力有余DevOps平台对K8s能力封装形象,只剩下5个Deployment的字段须要研发填写。从用户角度而言,这种设置十分好用简略。然而针对略微简单的利用,波及到利用状态治理,健康检查等等一系列的操作,此时这5个字段是不够的。 挑战四:CRD 扩大能力弱小,DevOps 平台无奈间接复用CRD(Customize Resource Definition)扩大能力弱小,简直所有软件都能够通过CRD的形式进行扩大,包含数据库、存储、平安、编排、依赖治理、公布等。然而对DevOps平台来说,下面接口并没有向用户裸露,导致无奈间接复用。 挑战五:DevOps 平台开发的新能力应用门槛高如果平台想要扩大一些能力,而原生的主动扩缩容能力不太适合,心愿开发定时的扩缩容YAML文件,随着业务状况而设置。但此时用户应用YAML的门槛十分高,不分明如何应用YAML。随着新能力开发越来越多,能力之间会呈现抵触,这也十分难以治理。 运维同学怎么晓得这个扩大能力怎么用?看 CRD?看配置文件?看 …… 文档? 扩大能力间呈现抵触,导致线上故障比方:CronHPA 和 默认 HPA 被同时装置给了同一个利用 K8s 扩大能力之间的抵触关系,如何无效治理?如何无效的对运维透出? 挑战六:不同 DevOps 平台须要齐全从新对接很多云原生实际中会遇到的问题,即须要定义非常复杂的YAML,这种形式能够解决企业外部所有问题,然而挑战在于很难与生态进行对接。如RDS,SLB的能力都嵌到YAML文件中,无奈复用,简直不具备原子化能力。同时无奈合作,无奈提供给兄弟部门或生态应用,只能给外部关闭生态应用。下层零碎不同利用对接DevOps平台时,须要写不同格局的YAML,这也是十分苦楚的。 难以了解,必须通过界面可视化透出无奈复用,简直不具备原子化能力无奈合作,只能外部关闭生态应用三 OAM利用模型的技术原理Component组件OAM中常见的概念是Component组件,齐全从研发角度定义的待部署单元。下图右侧是YAML中Component的例子,其中黄色局部能够灵便自定义。OAM中会定义规范的架构ContaineriseWorkload,示意工作负载局部,外面是待部署单元的具体形容。这时就能够解决关注点拆散的问题,帮忙利用侧工程师去掉很多细节,只须要关怀开发须要关注的端口号,镜像等等。 应答挑战一,在OAM中能够定义数据库表白资源须要应用云资源,Workload中能够依据本人的须要定义不同的组件,包含基于虚拟机的利用、或者老的Function利用。组件是利用开发者关怀的。 ...

August 27, 2020 · 1 min · jiezi

关于k8s:Kubernetes-119强调积极的态度

终于,咱们迎来了 Kubernetes 1.19 版本,这是2020年的第二个版本,也是迄今为止最长的公布周期,总共继续20周。它由33项加强性能组成。12个加强性能进入稳定版,18个加强性能进入测试版,13个加强性能进入alpha版。 因为 COVID-19、George Floyd 抗议以及咱们作为公布团队经验的其余一些全球性事件,因而1.19版本与惯例版本齐全不同。因为这些事件,咱们决定调整咱们的时间表,并让 SIG、工作组和贡献者有更多的工夫来实现工作。额定的工夫也让大家有工夫关注 Kubernetes 我的项目之外的生存,并确保他们的精神状态更加良好。 贡献者是 Kubernetes 的外围,Kubernetes 的行为准则要求人们都很优良,只管咱们的世界动荡不安,但咱们从社区中看到的只是平凡和谦卑。 次要主题将 Kubernetes 反对窗口减少到一年长期反对(LTS)工作组在2019年初进行的一项考察显示在以后的9个月反对期内,很大一部分 Kubernetes 用户未能降级。这一点以及考察中的其余反馈表明,如果将补丁反对期缩短至12-14个月,则30%的用户可能将其部署放弃在反对的版本上。无论用户应用的是自建版还是商业发行版,状况都是如此。因而,缩短反对期将导致超过 80% 的用户应用受反对的版本,而不是当初的 50-60%。一年一度的反对期可为用户提供所需的缓冲期,并且更合乎相熟的年度布局周期。从 Kubernetes 1.19 版本开始,反对窗口将缩短到一年。 贮存容量追踪传统上,Kubernetes 调度器基于这样的假如:集群中任何中央都能够应用额定的持久性存储,并具容量有限。拓扑束缚解决了第一点,但到目前为止,Pod 调度依然没有思考残余的存储容量可能不足以启动一个新的 pod。存储容量追踪是一个新的 Alpha 个性,它通过为 CSI 驱动程序增加一个 API 来解决这个问题,以报告存储容量,并在 Kubernetes 调度器中为 Pod 抉择节点时应用该信息。该性能可作为反对本地卷和其余容量限度较大的卷类型的动静预配置的根底。 通用长期存储Kubernetes 提供了卷插件,其生命周期与 Pod 绑定,可用作长期空间(例如内置的 emptydir 卷类型),也能够将一些数据加载到 Pod 中(例如内置的configmap 和 secret 卷类型)。新的通用暂存卷 alpha 性能容许任何现有的反对动静供给的存储驱动程序被用作 ephemeral 卷,并将该卷的生命周期绑定到 Pod。它能够用来提供不同于根磁盘的长期存储,例如长久内存或者该节点上的独立本地磁盘。反对所有用于卷供给的 StorageClass 参数。反对PersistentVolumeClaims 反对的所有性能,如存储容量跟踪、快照和还原以及卷的大小调整。 CSI Volume 衰弱监测CSI 健康状况监控的 Alpha 版本随 Kubernetes 1.19一起公布。该性能使 CSI 驱动程序可能与 Kubernetes 共享来自底层存储系统的异样卷情况,以便将其作为事件报告在 PVC 或 Pod 上。此性能是 Kubernetes 进行程序检测和解决单个卷衰弱问题的根底。 ...

August 27, 2020 · 2 min · jiezi

关于k8s:从PVC使用率看k8s-监控控制平面指标稳定性规范KEP

前言kubernetes家大业大,监控纷繁复杂,感兴趣的小伙伴能够看看我之前写的文章从容器监控kube-stats-metrics看k8s泛滥组件 k8s中pv使用率监控阐明尽管k8s最善于的是无状态的pod,不倡议有状态的存储型pod上然而总有些应用场景须要,比方statefulset应用的pv那么pv的使用率监控就十分有必要了咱们能够应用 kubelet_volume_stats_used_bytes/kubelet_volume_stats_capacity_bytes表征pod pv使用率 另外一种pv监控形式如果采纳云硬盘能够到对应的存储节点监控fs应用挂载状况能够轻松失去一个fs的应用状况而后依据k8s接口获取到pod和pv的映射关系向prometheus打点kubelet_volume_stats*采集原理追踪kubelet 启动 initializeModules--> fsResourceAnalyzer定时更新 podvolumestats --> updateCachedPodVolumeStats--> s.statsProvider.GetPods(从apiserver中获取的pod信息缓存到本地cache中)-->而后启动 calcAndStoreStats获取volume信息-->最终调用 volume的getmetrics()获取,路径可能是du/statFs/csi // Start eager background caching of volume stats.func (s *fsResourceAnalyzer) Start() { s.startOnce.Do(func() { if s.calcPeriod <= 0 { klog.Info("Volume stats collection disabled.") return } klog.Info("Starting FS ResourceAnalyzer") go wait.Forever(func() { s.updateCachedPodVolumeStats() }, s.calcPeriod) })}// updateCachedPodVolumeStats calculates and caches the PodVolumeStats for every Pod known to the kubelet.func (s *fsResourceAnalyzer) updateCachedPodVolumeStats() { oldCache := s.cachedVolumeStats.Load().(statCache) newCache := make(statCache) // Copy existing entries to new map, creating/starting new entries for pods missing from the cache for _, pod := range s.statsProvider.GetPods() { if value, found := oldCache[pod.GetUID()]; !found { newCache[pod.GetUID()] = newVolumeStatCalculator(s.statsProvider, s.calcPeriod, pod).StartOnce() } else { newCache[pod.GetUID()] = value } } // Stop entries for pods that have been deleted for uid, entry := range oldCache { if _, found := newCache[uid]; !found { entry.StopOnce() } } // Update the cache reference s.cachedVolumeStats.Store(newCache)}在k8s 1.17版本变动发现 kubelet_volume_stats_used_bytes等指标曾经不存在了 ...

August 11, 2020 · 2 min · jiezi

关于k8s:k8s节点亲和性

k8s节点亲和性Kubernetes中的调度策略能够大抵分为两种: 一种是全局的调度策略,要在启动调度器时配置,包含kubernetes调度器自带的各种predicates和priorities算法,具体能够参看上一篇文章;另一种是运行时调度策略,包含nodeAffinity(主机亲和性),podAffinity(POD亲和性)以及podAntiAffinity(POD反亲和性)。nodeAffinity 次要解决POD要部署在哪些主机,以及POD不能部署在哪些主机上的问题,解决的是POD和主机之间的关系。podAffinity 次要解决POD能够和哪些POD部署在同一个拓扑域中的问题(拓扑域用主机标签实现,能够是单个主机,也能够是多个主机组成的cluster、zone等。)podAntiAffinity次要解决POD不能和哪些POD部署在同一个拓扑域中的问题。它们解决的是Kubernetes集群外部POD和POD之间的关系。策略名称匹配指标反对的操作符反对拓扑域nodeAffinity主机标签In,NotIn,Exists,DoesNotExist,Gt,Lt不反对podAffinityPod标签In,NotIn,Exists,DoesNotExist反对PodAntiAffinityPod标签In,NotIn,Exists,DoesNotExist反对亲和性:利用A与利用B两个利用频繁交互,所以有必要利用亲和性让两个利用的尽可能的凑近,甚至在一个node上,以缩小因网络通信而带来的性能损耗。反亲和性:当利用的采纳多正本部署时,有必要采纳反亲和性让各个利用实例打散散布在各个node上,以进步HA,避免节点down掉,服务生效。nodeAffinity硬亲和性 affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: 硬亲和性 nodeSelectorTerms: 写多个满足其中一条就能够 - matchExpressions: 能够写多个满足必须同时满足 - key: disktype operator: In values: - ssd - hard软亲和性 affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 60 preference: matchExpressions: - {key: zone, operator: In, values: ["foo"]} - weight: 30 preference: matchExpressions: - {key: ssd, operator: Exists, values: []}同时指定nodeSelectorTerms和nodeSelector时必须同时满足nodeAffinity有多个nodeSelectorTerms ,pod只需满足一个nodeSelectorTerms多个matchExpressions ,pod必须都满足因为IgnoredDuringExecution,扭转labels不会影响曾经运行podPod affinity 因为业务的需要,有时会需要将pod调度到对立区域(node,机房)等,比方前端和和后端尽量放在一起,频繁交互的放在一起,这样能够缩小网络的开销,有时会出于平安思考,会将不通的pod放在不通区域,这时须要用到反亲和性。 <font color=#FF0000> requiredDuringSchedulingIgnoredDuringExecution, 硬束缚,肯定要满足,Pod的亲和性调度必须要满足后续定义的约束条件。 </font><font color=#FF0000> preferredDuringSchedulingIgnoredDuringExecution,软束缚,不肯定满足,Pod的亲和性调度会尽量满足后续定义的约束条件。 </font> pod亲和性会依据节点上正在运行的pod的标签来调度,而非node的标签,要求对节点和Pod两个条件进行匹配,其规定为:如果在具备指定标签的Node上运行了一个或多个符合条件的Pod,那么Pod应该运行在此Node上。反之怎不容许运行在此node上。能够依据kubernetes.io/hostname作为评判规范是否在一个域中。 Pod亲和性调度:podAffinity非亲和性调度:podAntiAffinity affinity: #定义亲和性 podAntiAffinity: # pod亲和性 requiredDuringSchedulingIgnoredDuringExecution: #硬束缚 - labelSelector: matchExpressions: - key: app operator: In values: - nacos topologyKey: kubernetes.io/hostname #域topologyKey: ...

August 11, 2020 · 1 min · jiezi

关于k8s:Kubernetes使用nfs做为动态存储

机器环境筹备应用StorageClass为k8s作为动静存储,大规模集群中可能会有很多PV,如果这些PV都须要运维手动来解决这也是一件很繁琐的事件,所以就有了动静供应概念,也就是Dynamic Provisioning。而咱们下面的创立的PV都是动态供应形式,也就是Static Provisioning。而动静供应的要害就是StorageClass,它的作用就是创立PV模板,进步工作效率,创PVC时会动静主动创立PV。 服务器用处10.4.2.104nfs服务器10.4.2.100-105k8s集群搭建nfs服务器10.4.2.104上搭建nfs服务器yum install rpcbindyum -y install nfs-utilskcat << EOF >> /etc/hosts/volumes 10.0.0.0/8(rw,no_root_squash,anonuid=998,anongid=994)EOFexportfs -rvsystemctl restart rpcbindsystemctl restart nfssystemctl enable nfsk8s所有节点装置nfs客户端yum -y install nfs-utilsK8S装置nfs-client创立RABCServiceAccountapiVersion: v1kind: ServiceAccountmetadata: name: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: storage-class---kind: ClusterRoleapiVersion: rbac.authorization.k8s.io/v1metadata: name: nfs-client-provisioner-runnerrules: - apiGroups: [""] resources: ["persistentvolumes"] verbs: ["get", "list", "watch", "create", "delete"] - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: ["get", "list", "watch", "update"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["events"] verbs: ["create", "update", "patch"]---kind: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata: name: run-nfs-client-provisionersubjects: - kind: ServiceAccount name: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: storage-classroleRef: kind: ClusterRole name: nfs-client-provisioner-runner apiGroup: rbac.authorization.k8s.io---kind: RoleapiVersion: rbac.authorization.k8s.io/v1metadata: name: leader-locking-nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: storage-classrules: - apiGroups: [""] resources: ["endpoints"] verbs: ["get", "list", "watch", "create", "update", "patch"]---kind: RoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata: name: leader-locking-nfs-client-provisioner namespace: storage-classsubjects: - kind: ServiceAccount name: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: storage-classroleRef: kind: Role name: leader-locking-nfs-client-provisioner apiGroup: rbac.authorization.k8s.iokubectl apply -f rabc.yaml装置nfs-clientapiVersion: apps/v1kind: Deploymentmetadata: name: nfs-client-provisioner labels: app: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: storage-classspec: replicas: 1 selector: matchLabels: app: nfs-client-provisioner strategy: type: Recreate selector: matchLabels: app: nfs-client-provisioner template: metadata: labels: app: nfs-client-provisioner spec: serviceAccountName: nfs-client-provisioner containers: - name: nfs-client-provisioner image: harbor-k8s.iwgame.com/containers/nfs-client-provisioner:latest volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes/ env: - name: PROVISIONER_NAME value: g.iwgame.com/nfs - name: NFS_SERVER value: 10.4.2.104 - name: NFS_PATH value: /volumes volumes: - name: nfs-client-root nfs: server: 10.4.2.104 path: /volumeskubectl apply -f deployment.yaml创立StorageClassapiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: iwgame-nfs-storage annotations: storageclass.kubernetes.io/is-default-class: "true"provisioner: g.iwgame.com/nfs # or choose another name, must match deployment's env PROVISIONER_NAME'reclaimPolicy: Retainparameters: archiveOnDelete: "false"创立PVC测试

August 10, 2020 · 2 min · jiezi

关于k8s:支持Pod-绑定静态-IP-基于K8s的自定义控制器Enhanced-Statefulset

云妹导读: 以后,Kubernetes曾经成为云原生的事实标准, Kubernetes原生反对了功能强大的控制器——deployment 、statefulset  、daemonset。但在理论业务场景中,原生控制器无奈满足一些简单和大规模场景中的业务需要。京东智联云开发团队联合多年云原生开发与应用教训,推出了自定义控制器Enhanced statefulset。本文将把咱们的产品性能、技术思考和实现细节全面展示给云原生用户和开发者,以期帮忙大家更好地应用Kubernetes 开始本人的云原生之路。 随着云原生概念逐步深入人心,越来越多的用户开始承受和践行云原生的设计与理念。Kubernetes作为容器治理引擎,提供了弱小的容器编排能力,反对不可变基础设施与申明式Openapi,同时隔离了底层基础设施差别,曾经成为云原生的基石和事实标准。Kubernetes原生反对功能强大的控制器,例如deployment 、statefulset  、daemonset等,能够解决很多用户场景。但随着 Kubernetes 的应用范畴越来越广,原生的控制器曾经无奈满足一些简单和大规模场景中的业务需要。 以京东团体业务为例,因为历史起因,团体内很多根底运维业务包含日志、监控、拜访策略管制、服务发现等都是以IP作为实例惟一标识,这就要求Pod实例可能反对动态IP绑定。同时,咱们并不是简略地为了Kubernetes而上Kubernetes,而是须要尽量利用Kubernetes为业务提供更多的DevOps能力,比方更丰盛的降级策略,故障主动迁徙等。 基于这些思考,最终咱们决定基于CRD扩大(CustomResourceDefinitions,即自定义资源)的机制,通过自定义控制器的形式来提供Pod绑定动态IP性能。这就是本篇文章要讲的产品——Enhanced statefulset。 顾名思义,Enhanced statefulset就是咱们在statefulset的根底上对控制器做了进一步的扩大。它次要解决Pod绑定动态IP问题,同时也解决了statefulset在降级过程中不容许同时降级多个实例的限度。另外,它还能够在节点故障时反对Pod和IP的迁徙。 上面和大家分享一下Enhanced statefulset的外围性能个性: 后面曾经提到了动态IP的重要场景是业务依赖的周边组件都以IP作为实例惟一标识,所以上到Kubernetes后依然须要Pod实例放弃IP不变。置信很多用户也面临着相似的问题,上面就来分享一下实现原理。 咱们次要是通过对Enhanced Statefulset Controller 、 Scheduler、CNI这几个模块扩大来反对Enhanced Statefulset的Pod绑定动态IP。具体模块关系和性能如下图所示: ▲模块关系图▲ Enhanced Statefulset Controller 对动态IP的治理次要是保护更新Static IP CR来实现的。当Controller收到创立申请时,会首先查看要创立的实例是否曾经有对应的static IP CR记录,若记录不存在则会创立一个新的记录。在稍后scheduler实现调度,CNI实现动态IP调配后,controller会监听Pod信息并将其更新到Static IP CR中。反之若创立实例时,对应的static IP CR记录曾经存在则示意这个Pod是删除重建,Controller会将static IP CR中的信息更新到Pod上,scheduler和CNI依据pod上的配置进行亲和性调度和IP调配。 StaticIP CRD中记录了负载类型、负载名称、节点、IP和Pod信息。其中IP信息在Pod实例上以annotation taticip.jke.jdcloud.com/ip-address 形式出现,CNI就是依据这个字段来决定要调配的IP地址。节点信息则是通过affinity属性在pod上出现,这样scheduler就不须要感知节点和IP的拓扑信息,只有依照亲和性调度就能够将Pod调度到动态IP所在的节点上,简化了scheduler的解决逻辑。 1apiVersion: "jke.jdcloud.com/v1" 2kind: StaticIP 3metadata: 4  name: {{workload}}-{{podname}}-{{ipaddress}} 5spec: 6  Ref: {{workload-name}}      // 所属 workload 实例名称,如 deployment-xxxx 7  Kind: {{workload}}          // workload 类型, 如 deployment 8  Node: Node-{{name}}         // node 名称, 如 node-xxxx 9  IP: {{ipaddress}}           // 绑定的 ip 地址, 如 10.10.0.110  Pod: {{pod-name}}           // pod 名称: pod-xxxxx〈〈〈左右滑动以查看残缺代码 〉〉〉 咱们对scheduler做的扩大次要是解决Pod资源预留问题。失常流程中当绑定动态IP的Pod删除后,Pod所占用的资源也会被开释,如果有其余新调度的Pod到这个节点上就会占用以后节点的资源。这时如果绑定动态IP的Pod在此节点重建可能就会因为资源有余而失败。为了解决这个问题,咱们对scheduler做了扩大: 新增缓存:原有 Node 缓存根底上新增 staticIPNode 缓存,用于计算和缓存 staticIPPod 资源占用状况、缓存 IP 数量、Pod cpu/内存 使用量;新增predicate :PodFitsResourcesWithStaticIPPodPred Node 现有资源根底上基于 staticIPPod 占用资源再次过滤,达到资源预占目标;CheckPodAnnotationWithStaticIPPred 查看pod 是否蕴含 static ip 的指定 node annotation, 并仅保留指定 node 后果只 fit node 列表。概括起来外围思路就是将动态IP Pod所占用的资源作为一种非凡资源独自标识,在调度时进行匹配调度达到资源预占目标。 ...

August 7, 2020 · 1 min · jiezi

关于k8s:限时开放下载219页阿里技术Knative-云原生应用开发指南

你理解云原生和Knative吗? 当他人探讨此话题的时候,你是否会不知所云? 什么是Knative? Knative 是 Google 在 2018 的 Google Cloud Next 大会上公布的一款基于 Kubernetes 的 Serverless 框架。 Knative 的一个很重要的指标就是制订云原生、跨平台的 Serverless 编排规范。它的劣势在于: 基于 Kubernetes 实现 Serverless 编排;基于 Istio 实现服务的接入、服务路由的治理以及灰度公布等性能。 (Knative 体系下各个角色的协作关系) 为了进一步不便大家了解 Knative,特地给大家举荐由阿里云容器平台技术专家牛秋霖(冬岛)及阿里云容器平台高级开发工程师李鹏(元毅)联合本身的实践经验,编排的《Knative 云原生利用开发指南》,心愿可能通过文章中 25 篇重点内容帮忙更多技术爱好者疾速把握 Knative 的利用 Serverless 编排技能,揭开 Knative 的神秘面纱。 如何收费下载? 长按辨认二维码,即可收费下载此书 为什么你要读这本书? 如果你是开发者 本书能够让你疾速把握 Knative 的利用 Serverless 编排技能。应用Serverless框架之后,开发者只须要编写代码,以及配置文件,而后运行Build和Deploy就能把利用主动部署到集群,其余工作都由Knative主动解决 如果你是管理者 通过本书的介绍和案例深刻理解企业为什么须要利用的 Serverless 编排;如何对一般利用进行 Serverless 编排;利用编排和 IaaS 无服务器计算的关系以及为什么会是 Knative 等问题。 ...

July 27, 2020 · 1 min · jiezi

关于k8s:限时开放下载219页阿里技术Knative-云原生应用开发指南

你理解云原生和Knative吗? 当他人探讨此话题的时候,你是否会不知所云? 什么是Knative? Knative 是 Google 在 2018 的 Google Cloud Next 大会上公布的一款基于 Kubernetes 的 Serverless 框架。 Knative 的一个很重要的指标就是制订云原生、跨平台的 Serverless 编排规范。它的劣势在于: 基于 Kubernetes 实现 Serverless 编排;基于 Istio 实现服务的接入、服务路由的治理以及灰度公布等性能。 (Knative 体系下各个角色的协作关系) 为了进一步不便大家了解 Knative,特地给大家举荐由阿里云容器平台技术专家牛秋霖(冬岛)及阿里云容器平台高级开发工程师李鹏(元毅)联合本身的实践经验,编排的《Knative 云原生利用开发指南》,心愿可能通过文章中 25 篇重点内容帮忙更多技术爱好者疾速把握 Knative 的利用 Serverless 编排技能,揭开 Knative 的神秘面纱。 如何收费下载? 长按辨认二维码,即可收费下载此书 为什么你要读这本书? 如果你是开发者 本书能够让你疾速把握 Knative 的利用 Serverless 编排技能。应用Serverless框架之后,开发者只须要编写代码,以及配置文件,而后运行Build和Deploy就能把利用主动部署到集群,其余工作都由Knative主动解决 如果你是管理者 通过本书的介绍和案例深刻理解企业为什么须要利用的 Serverless 编排;如何对一般利用进行 Serverless 编排;利用编排和 IaaS 无服务器计算的关系以及为什么会是 Knative 等问题。 ...

July 27, 2020 · 1 min · jiezi

关于k8s:一文入门Kubernetes

Kubernetes(通常缩写为K8S)是容器编排平台。 Kubernetes提供了反对简单容器应用程序所需的所有。对于开发人员和经营人员来说,这是最便捷,最受欢迎的框架,简直所有组织的DevOps团队都宽泛应用它。 Kubernetes对计算机集群而言,就像操作系统对计算机而言。为了方便管理和服务发现,Kubernetes将组成一个应用程序的容器分组为逻辑单元。这对于微服务应用程序特地有用。 只管Kubernetes在Linux上运行,但它与平台无关,能够在裸机,虚拟机,云实例或OpenStack上运行。最新版本的Kubernetes曾经反对在Windows上运行。 Kubernetes集群中的计算机或节点分为管制立体和工作负载立体。Kubernetes 集群架构Kubernetes集群由分为两组的节点组成: 一组master节点,它们承载着管制立体组件,它们是零碎的大脑,因为它们管制着整个集群。一组形成工作负载立体的工作节点,工作负载(或应用程序)在此运行。 这两个立体独特组成了Kubernetes集群。Kubernetes Master 节点这是Kubernetes控制面板或管制立体。这里做出无关集群的决策,例如调度和检测/响应集群事件。master服务器的组件能够在集群中的任何节点上运行。以下是每个要害组件的细分: API Server集群数据存储 (etcd)Controller ManagerSchedulerDashboard (可选) 让咱们逐个探讨这些组件。 API Server 这是Kubernetes控制面板中惟一用户可拜访的API的组件,并且是你将与之交互的惟一主组件。 API Server公开了一个restful的Kubernetes API,并应用了JSON清单文件。 Kubernetes API Server公开了RESTful Kubernetes API。应用集群和其余Kubernetes组件的工程师通过此API创建对象。 集群数据存储 Kubernetes应用ETCD作为数据存储。这是一个一致性且高可用的键值存储,用于长久存储所有API对象。 因为API Server自身是无状态的,因而etcd分布式数据存储将长久保留通过API创立的对象。API Server 是与etcd通信的惟一组件。 Controller Manager kube-controller manager,它运行所有解决集群中工作的控制器。这些包含节点控制器,正本控制器,端点控制器以及服务帐户和secret控制器。这些控制器中的每一个都独自工作以维持所需状态。 控制器使你通过API创立的对象依照想要的状态运行。它们中的大多数仅创立其余对象,然而有些还与内部零碎通信(例如,通过其API的云提供商)。 Scheduler 调度程序监督新创建的Pod(一个或多个容器的组),并将其调配给节点。 调度程序决定每个应用程序实例应在哪个工作程序节点上运行。 master节点和工作节点的组件之间就是这样进行交互的。Kubernetes 工作节点 master节点解决和治理集群,而工作节点运行容器并提供Kubernetes运行时环境。 次要组件有: KubeletContainer runtimeKube-proxy 让咱们逐个探讨这些组件。 Kubelet 工作节点蕴含一个kubelet。这是次要的节点代理。它监督API服务器以查找已调配给其节点的Pod。 Kubelet执行工作并保护向主节点报告pod状态的反向通道。 Kubelet是与API Server进行对话并治理在其节点上运行的应用程序的代理。它通过API报告这些应用程序和节点的状态。 Container Runtime 每个pod内都有容器,kubelet通过Docker运行这些容器(拉取镜像,启动和进行容器等)。它还定期执行任何申请的容器活动性探测。它反对Docker和CRI-O等。 容器运行时,能够是Docker或与Kubernetes兼容的任何其余运行时。它依照Kubelet的指令在容器中运行你的应用程序。 Kube-proxy 这是节点的网络大脑,负责保护主机上的网络规定并执行连贯转发。它还负责服务中所有Pod的负载平衡。 Kubernetes服务代理(Kube-proxy)对应用程序之间的网络流量进行负载平衡。 附加组件大多数Kubernetes集群还蕴含其余几个组件。这包含DNS服务器,网络插件,日志记录代理等。 它们通常在工作节点上运行,但也能够配置为在master节点上运行。 Kubernetes 实战 ...

July 26, 2020 · 1 min · jiezi

关于k8s:一文入门Kubernetes

Kubernetes(通常缩写为K8S)是容器编排平台。 Kubernetes提供了反对简单容器应用程序所需的所有。对于开发人员和经营人员来说,这是最便捷,最受欢迎的框架,简直所有组织的DevOps团队都宽泛应用它。 Kubernetes对计算机集群而言,就像操作系统对计算机而言。为了方便管理和服务发现,Kubernetes将组成一个应用程序的容器分组为逻辑单元。这对于微服务应用程序特地有用。 只管Kubernetes在Linux上运行,但它与平台无关,能够在裸机,虚拟机,云实例或OpenStack上运行。最新版本的Kubernetes曾经反对在Windows上运行。 Kubernetes集群中的计算机或节点分为管制立体和工作负载立体。Kubernetes 集群架构Kubernetes集群由分为两组的节点组成: 一组master节点,它们承载着管制立体组件,它们是零碎的大脑,因为它们管制着整个集群。一组形成工作负载立体的工作节点,工作负载(或应用程序)在此运行。 这两个立体独特组成了Kubernetes集群。Kubernetes Master 节点这是Kubernetes控制面板或管制立体。这里做出无关集群的决策,例如调度和检测/响应集群事件。master服务器的组件能够在集群中的任何节点上运行。以下是每个要害组件的细分: API Server集群数据存储 (etcd)Controller ManagerSchedulerDashboard (可选) 让咱们逐个探讨这些组件。 API Server 这是Kubernetes控制面板中惟一用户可拜访的API的组件,并且是你将与之交互的惟一主组件。 API Server公开了一个restful的Kubernetes API,并应用了JSON清单文件。 Kubernetes API Server公开了RESTful Kubernetes API。应用集群和其余Kubernetes组件的工程师通过此API创建对象。 集群数据存储 Kubernetes应用ETCD作为数据存储。这是一个一致性且高可用的键值存储,用于长久存储所有API对象。 因为API Server自身是无状态的,因而etcd分布式数据存储将长久保留通过API创立的对象。API Server 是与etcd通信的惟一组件。 Controller Manager kube-controller manager,它运行所有解决集群中工作的控制器。这些包含节点控制器,正本控制器,端点控制器以及服务帐户和secret控制器。这些控制器中的每一个都独自工作以维持所需状态。 控制器使你通过API创立的对象依照想要的状态运行。它们中的大多数仅创立其余对象,然而有些还与内部零碎通信(例如,通过其API的云提供商)。 Scheduler 调度程序监督新创建的Pod(一个或多个容器的组),并将其调配给节点。 调度程序决定每个应用程序实例应在哪个工作程序节点上运行。 master节点和工作节点的组件之间就是这样进行交互的。Kubernetes 工作节点 master节点解决和治理集群,而工作节点运行容器并提供Kubernetes运行时环境。 次要组件有: KubeletContainer runtimeKube-proxy 让咱们逐个探讨这些组件。 Kubelet 工作节点蕴含一个kubelet。这是次要的节点代理。它监督API服务器以查找已调配给其节点的Pod。 Kubelet执行工作并保护向主节点报告pod状态的反向通道。 Kubelet是与API Server进行对话并治理在其节点上运行的应用程序的代理。它通过API报告这些应用程序和节点的状态。 Container Runtime 每个pod内都有容器,kubelet通过Docker运行这些容器(拉取镜像,启动和进行容器等)。它还定期执行任何申请的容器活动性探测。它反对Docker和CRI-O等。 容器运行时,能够是Docker或与Kubernetes兼容的任何其余运行时。它依照Kubelet的指令在容器中运行你的应用程序。 Kube-proxy 这是节点的网络大脑,负责保护主机上的网络规定并执行连贯转发。它还负责服务中所有Pod的负载平衡。 Kubernetes服务代理(Kube-proxy)对应用程序之间的网络流量进行负载平衡。 附加组件大多数Kubernetes集群还蕴含其余几个组件。这包含DNS服务器,网络插件,日志记录代理等。 它们通常在工作节点上运行,但也能够配置为在master节点上运行。 Kubernetes 实战 ...

July 26, 2020 · 1 min · jiezi

关于k8s:全网最详细的-K8s-Service-不能访问排查流程

对于新装置的 Kubernetes,经常出现的一个问题是 Service 没有失常工作。如果您曾经运行了 Deployment 并创立了一个 Service,然而当您尝试拜访它时没有失去响应,心愿这份文档能帮忙您找出问题所在。 先来相熟下Service工作逻辑: 为了实现本次演练的目标,咱们先运行几个 Pod。 $ kubectl run hostnames --image=k8s.gcr.io/serve_hostname \ --labels=app=hostnames \ --port=9376 \ --replicas=3 deployment.apps/hostnames created确认您的 Pods 是运行状态: $ kubectl get pods -l app=hostnamesNAME                        READY     STATUS    RESTARTS   AGEhostnames-632524106-bbpiw   1/1       Running   0          2mhostnames-632524106-ly40y   1/1       Running   0          2mhostnames-632524106-tlaok   1/1       Running   0          2m问题1:Service 存在吗?仔细的读者会留神到咱们还没有真正创立一个 Service - 其实这是咱们无意的。这是一个有时会被忘记的步骤,也是第一件要查看的事件。 那么,如果我试图拜访一个不存在的 Service,会产生什么呢?假如您有另一个 Pod,想通过名称应用这个 Service,您将失去如下内容: u@pod$ wget -O- hostnamesResolving hostnames (hostnames)... failed: Name or service not known.wget: unable to resolve host address 'hostnames'因而,首先要查看的是 Service 是否的确存在: $ kubectl get svc hostnamesNo resources found.Error from server (NotFound): services "hostnames" not found咱们曾经有一个罪魁祸首了,让咱们来创立 Service。就像后面一样,这里的内容仅仅是为了步骤的执行 - 在这里您能够应用本人的 Service 细节。 $ kubectl expose deployment hostnames --port=80 --target-port=9376service/hostnames exposed再查问一遍,确定一下: $ kubectl get svc hostnamesNAME        TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGEhostnames   ClusterIP   10.0.1.175   <none>        80/TCP    5s与后面雷同,这与您应用 YAML 启动的 Service 一样: apiVersion: v1 kind: Service metadata: name: hostnames spec: selector: app: hostnames ports: - name: default protocol: TCP port: 80 targetPort: 9376当初您能够确认 Service 存在。 问题2:Service 是否通过 DNS 工作?从雷同 Namespace 下的 Pod 中运行: u@pod$ nslookup hostnamesAddress 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.localName:      hostnamesAddress 1: 10.0.1.175 hostnames.default.svc.cluster.local如果失败,那么您的 Pod 和 Service 可能位于不同的 Namespace 中,请尝试应用限定命名空间的名称: ...

July 18, 2020 · 3 min · jiezi

Microk8s配置

根本配置设置别名snap alias microk8s.kubectl kubectl能够用snap unalias 撤销别名指定 查看状态microk8s status --wait-ready启用插件能够用 microk8s enable --help 查看可用的插件 microk8s enable dns dashboard ingress查看组件状况microk8s.inspect通常会提醒 WARNING: IPtables FORWARD policy is DROP. Consider enabling traffic forwarding with: sudo iptables \-P FORWARD ACCEPT应用ufw敞开防火墙端口 sudo ufw allow in on cbr0 && sudo ufw allow out on cbr0sudo ufw default allow routedsudo iptables \-P FORWARD ACCEPT创立利用kubectl create deployment nginx --image=nginx--image 为指定的docker镜像地址

July 13, 2020 · 1 min · jiezi

Kubernetes各版本对应支持的docker版本列表

Kubernetes各版本对应反对的docker版本列表

July 13, 2020 · 1 min · jiezi

Pod-就地升级3kubelet-通过hash管理容器版本

k8s原生并不反对就地降级。诸如deployment等工作负载在降级的过程中,间接对Pod进行recreate。 实现容器的就地降级的另外一个前提是kubelet通过容器hash 来治理容器版本。 当创立一个Pod的时候,kubelet会计算每个容器的hash,并且把该hash值写到ContainerStatus中,该status的定义如下: // Status represents the status of a container.type Status struct { // ID of the container. ID ContainerID // Name of the container. Name string // Status of the container. State State // Creation time of the container. CreatedAt time.Time // Start time of the container. StartedAt time.Time // Finish time of the container. FinishedAt time.Time // Exit code of the container. ExitCode int // Name of the image, this also includes the tag of the image, // the expected form is "NAME:TAG". Image string // ID of the image. ImageID string // Hash of the container, used for comparison. Hash uint64 // Number of times that the container has been restarted. RestartCount int // A string explains why container is in such a status. Reason string // Message written by the container before exiting (stored in // TerminationMessagePath). Message string}其中的Hashfiled 正是咱们明天讲到的hash。 ...

July 11, 2020 · 7 min · jiezi

Pod-就地升级2Readiness-gates

什么是Readiness gates?Readiness gates,又被称为pod “ready++”,该个性kubernetes1.11被引入,在kubernetes1.14 达到稳固状态。 在这之前,咱们通过设置readiness probe 来决定是否Pod能够开始提供服务--即Pod的地址是否能够呈现在对应endpoints的列表中。然而此时可能相关联的其余根底服务并没有真正准备就绪。 例如,在部署滚动更新期间,一个新的Pod准备就绪。另一方面,因为任何起因(例如api machinery,endpoints controller,kube-proxy,iptables或根底构造编程的速度迟缓),网络策略和负载平衡器尚未为新的pod准备就绪。这可能会导致服务中断或后端容量失落。在极其状况下,如果滚动更新在任何新的替换Pod理论开始为流量提供服务之前实现,则将导致服务中断。 Readiness gates 正是为了解决此类问题呈现的。它给与了Pod之外组件管制Pod 就绪的能力。 Readiness gates取决于Pod的status.condition字段的以后状态。如果Kubernetes在Pod的status.conditions字段中找不到这样的条件,则该条件的状态默认为“ False”。 这是一个例子: kind: Pod...spec: readinessGates: - conditionType: "www.example.com/feature-1"status: conditions: - type: Ready # a built in PodCondition status: "False" lastProbeTime: null lastTransitionTime: 2018-01-01T00:00:00Z - type: "www.example.com/feature-1" # an extra PodCondition status: "False" lastProbeTime: null lastTransitionTime: 2018-01-01T00:00:00Z containerStatuses: - containerID: docker://abcd... ready: true...此时对于应用自定义条件的Pod,仅当以下两个语句均实用时,该Pod才被评估为就绪: Pod中的所有容器均已准备就绪。ReadinessGates中指定的所有条件均为True。当Pod的容器准备就绪,但至多短少一个自定义条件或False时,kubelet将Pod的条件设置为ContainersReady。 如何应用Readiness gates?kubectl patch命令不反对批改对象状态。要为Pod设置这些状态条件,应用程序和operator应用PATCH操作。能够应用Kubernetes客户端库编写代码来设置Pod筹备状态的自定义Pod条件。如何使ReadinessGates对K8s API用户通明。换句话说,K8s API用户无需指定ReadinessGates即可应用特定性能。这容许现有清单仅与须要ReadinessGate的性能一起应用。每个性能都将承当注入ReadinessGate的工作,并放弃其自定义Pod条件放弃同步。能够在容器创立时应用变异的Webhook注入ReadinessGate。Pod创立后,只有其ReadinessGate存在于PodSpec中,每个性能都负责使其自定义Pod条件放弃同步。这能够通过运行k8s控制器来同步相干Pod上的条件来实现。这是为了确保即便在API服务器上产生灾难性故障(例如,数据失落)时,PodStatus也是可察看和可复原的。就地降级和Readiness gates为什么说没有Readiness gates就没有就地降级?原生的Pod降级策略是recreate。一系列的措施保障了Pod在降级过程中,不会服务流量。 ...

July 11, 2020 · 1 min · jiezi

Pod-就地升级1Docker-Image-IDs

前言Docker 镜像是用于创立容器的只读模板,并提供了基于多层文件和门路的有序联结文件系统,该文件系统能够与其余镜像和容器共享。共享镜像层是Docker平台的根本组成部分,并且通过实现写时复制(COW)机制来实现。在其生命周期内,如果容器须要从提供其文件系统的只读映像中更改文件,它将在进行更改之前将文件复制到其本人的公有读写层。 在Docker镜像构建过程中会创立一个层或"diff",并在容器中运行命令时产生的后果,该命令会生成新的或批改的文件和目录。这些新的或批改的文件和目录被“committed”为新的层。 历史的角度历史上(Docker v1.10之前的版本),每次因为'commit'操作而创立新层时,Docker还会创立一个对应的镜像,该镜像由随机生成的256位UUID标识,通常称为镜像ID(在UI中以短12位十六进制字符串或长64位十六进制字符串示意)。 Docker将层内容存储在目录中,该目录的名称与镜像ID雷同。在外部,镜像由配置对象组成,该对象保留镜像的特色,包含其ID和镜像的父镜像的ID。这样,Docker可能为容器构建文件系统,每个镜像顺次援用其父级和相应的层内容,直到达到没有父级的根底镜像为止。每个镜像也能够用有意义的名称标记(例如my_image:1.0),但这通常是为叶子镜像保留的。如下图所示: 应用docker inspect命令: $ docker inspect my_image:1.0[ { "Id": "ca1f5f48ef431c0818d5e8797dfe707557bdc728fe7c3027c75de18f934a3b76", "Parent": "91bac885982d2d564c0e1869e8b8827c435eead714c06d4c670aaae616c1542c" ... ...这种办法能够在继续的一段时间内很好地为Docker服务,然而因为种种原因,随着工夫的推移,这种办法被认为不是最佳的。推动改革的次要能源之一是,短少一种办法来检测图像内容是否在推送或从注册表中拉出时被篡改,例如Docker Hub。这引起了整个社区的强烈批评,并导致了一系列变动,最终造成了内容可寻址的ID。 内容可寻址的IDs从Docker v1.10开始,镜像和镜像层通常不再是同义词。相同,镜像间接援用最终有助于派生容器的文件系统的一层或多层。 当初,通过摘要标识层,摘要的格局为:algorithm:hex;例如: sha256:fc92eec5cac70b0c324cec2933cd7db1c0eae7c9e2649e42d02e77eb6da0d15f十六进制元素是通过将算法(SHA256)利用于镜像层内容来计算的。如果内容更改,则计算的摘要也将更改,这意味着Docker能够应用已公布的摘要查看检索到的层内容,以验证其内容。层没有镜像或属于镜像的概念,它们只是文件和目录的汇合。 Docker镜像当初蕴含一个配置对象,该对象(除其余外)蕴含一个层摘要的有序列表,这使Docker引擎可能参考层摘要而不是父镜像来组装容器的文件系统。镜像ID也是摘要,并且是镜像配置对象的计算得出的SHA256哈希,其中蕴含有助于镜像文件零碎定义的各层的摘要。下图形容了Docker v1.10之后镜像和层之间的关系: 镜像和层的摘要已缩短,以进步可读性。 当初,用于存储层内容的diff目录以一个随机生成的“cache ID”命名,并且Docker引擎保护该层及其cache ID之间的链接,以便它晓得在磁盘上的地位。 因而,当从注册表中提取Docker镜像,并应用docker history命令显示其内容时,输入将提供相似于以下内容: $ docker history swarmIMAGE CREATED CREATED BY SIZE COMMENTc54bba046158 9 days ago /bin/sh -c #(nop) CMD ["--help"] 0 B <missing> 9 days ago /bin/sh -c #(nop) ENTRYPOINT &{["/swarm"]} 0 B <missing> 9 days ago /bin/sh -c #(nop) VOLUME [/.swarm] 0 B <missing> 9 days ago /bin/sh -c #(nop) EXPOSE 2375/tcp 0 B <missing> 9 days ago /bin/sh -c #(nop) ENV SWARM_HOST=:2375 0 B <missing> 9 days ago /bin/sh -c #(nop) COPY dir:b76b2255a3b423981a 0 B <missing> 9 days ago /bin/sh -c #(nop) COPY file:5acf949e76228329d 277.2 kB <missing> 9 days ago /bin/sh -c #(nop) COPY file:a2157cec2320f541a 19.06 MB该命令提供无关镜像及其组成的层的详细信息。 IMAGE字段中除镜像的一层以外的所有<missing>值都具备误导性。它传播了谬误的提醒,然而没有谬误,因为层不再与相应的镜像和ID同义。我认为将字段留空会更适合。同样,镜像ID仿佛与最上层相关联,但实际上,镜像ID不“属于”任何层。而是,这些层独特属于镜像,并提供其文件系统定义。 ...

July 11, 2020 · 2 min · jiezi

从容器监控kubestatsmetrics看k8s众多组件

k8s监控组织架构 指标阐明零碎指标分为节点/容器资源应用和DaemonSet运行的资源服务指标分为Kubernetes根底结构组件产生的和利用pod产生的kube-stats-metrics- job_name: kube-state-metrics honor_timestamps: false scrape_interval: 30s scrape_timeout: 10s metrics_path: /metrics scheme: http static_configs: - targets: - kube-state-metrics.kube-admin:8080k8s apiserver是什么k8s API Server提供了k8s各类资源对象(pod,RC,Service等)的增删改查及watch等HTTP Rest接口,是整个零碎的数据总线和数据中心 采集原理kube-state-metrics应用client-go与Kubernetes集群通信,一直轮询api-server 初始化metric store family// E:\go_path\src\k8s.io\kube-state-metrics\internal\store\builder.govar availableStores = map[string]func(f *Builder) cache.Store{ "certificatesigningrequests": func(b *Builder) cache.Store { return b.buildCsrStore() }, "configmaps": func(b *Builder) cache.Store { return b.buildConfigMapStore() }, "cronjobs": func(b *Builder) cache.Store { return b.buildCronJobStore() }, "daemonsets": func(b *Builder) cache.Store { return b.buildDaemonSetStore() }, "deployments": func(b *Builder) cache.Store { return b.buildDeploymentStore() }, "endpoints": func(b *Builder) cache.Store { return b.buildEndpointsStore() }, "horizontalpodautoscalers": func(b *Builder) cache.Store { return b.buildHPAStore() }, "ingresses": func(b *Builder) cache.Store { return b.buildIngressStore() }, "jobs": func(b *Builder) cache.Store { return b.buildJobStore() }, "leases": func(b *Builder) cache.Store { return b.buildLeases() }, "limitranges": func(b *Builder) cache.Store { return b.buildLimitRangeStore() }, "mutatingwebhookconfigurations": func(b *Builder) cache.Store { return b.buildMutatingWebhookConfigurationStore() }, "namespaces": func(b *Builder) cache.Store { return b.buildNamespaceStore() }, "networkpolicies": func(b *Builder) cache.Store { return b.buildNetworkPolicyStore() }, "nodes": func(b *Builder) cache.Store { return b.buildNodeStore() }, "persistentvolumeclaims": func(b *Builder) cache.Store { return b.buildPersistentVolumeClaimStore() }, "persistentvolumes": func(b *Builder) cache.Store { return b.buildPersistentVolumeStore() }, "poddisruptionbudgets": func(b *Builder) cache.Store { return b.buildPodDisruptionBudgetStore() }, "pods": func(b *Builder) cache.Store { return b.buildPodStore() }, "replicasets": func(b *Builder) cache.Store { return b.buildReplicaSetStore() }, "replicationcontrollers": func(b *Builder) cache.Store { return b.buildReplicationControllerStore() }, "resourcequotas": func(b *Builder) cache.Store { return b.buildResourceQuotaStore() }, "secrets": func(b *Builder) cache.Store { return b.buildSecretStore() }, "services": func(b *Builder) cache.Store { return b.buildServiceStore() }, "statefulsets": func(b *Builder) cache.Store { return b.buildStatefulSetStore() }, "storageclasses": func(b *Builder) cache.Store { return b.buildStorageClassStore() }, "validatingwebhookconfigurations": func(b *Builder) cache.Store { return b.buildValidatingWebhookConfigurationStore() }, "volumeattachments": func(b *Builder) cache.Store { return b.buildVolumeAttachmentStore() }, "verticalpodautoscalers": func(b *Builder) cache.Store { return b.buildVPAStore() },}初始化watchfunc 接管后果// E:\go_path\src\k8s.io\kube-state-metrics\internal\store\builder.go// reflectorPerNamespace creates a Kubernetes client-go reflector with the given// listWatchFunc for each given namespace and registers it with the given store.func (b *Builder) reflectorPerNamespace( expectedType interface{}, store cache.Store, listWatchFunc func(kubeClient clientset.Interface, ns string) cache.ListerWatcher,) { lwf := func(ns string) cache.ListerWatcher { return listWatchFunc(b.kubeClient, ns) } lw := listwatch.MultiNamespaceListerWatcher(b.namespaces, nil, lwf) instrumentedListWatch := watch.NewInstrumentedListerWatcher(lw, b.metrics, reflect.TypeOf(expectedType).String()) reflector := cache.NewReflector(sharding.NewShardedListWatch(b.shard, b.totalShards, instrumentedListWatch), expectedType, store, 0) go reflector.Run(b.ctx.Done())}指标列举ConfigMap指标: ConfigMap是什么eg: configmap信息kube_configmap_info{configmap="xxx",instance="kube-state-metrics.kube-admin:8080",job="kube-state-metrics",namespace="xxx"}CronJob指标 CronJob是什么eg: cronjob下次调度工夫kube_cronjob_next_schedule_time{cronjob="abc",instance="kube-state-metrics.kube-admin:8080",job="kube-state-metrics",namespace="abc"} 1594306800DaemonSet指标 DaemonSet是什么eg: ready daemonsetkube_daemonset_status_number_ready{daemonset="npd",instance="kube-state-metrics.kube-admin:8080",job="kube-state-metrics",namespace="kube-admin"} 6Deployment Metrics Deployment是什么eg : 不衰弱的podkube_deployment_status_replicas_unavailable{deployment="coredns",instance="kube-state-metrics.kube-admin:8080",job="kube-state-metrics",namespace="kube-system"}Endpoints Metrics : service向其发送流量的对象的IP地址 ...

July 10, 2020 · 2 min · jiezi

邀您参与-阿里巴巴如何扩展-K8s-调度器支持-AI-和大数据任务

简介: 2020 年 7 月 15 日上午 10:00,《阿里巴巴如何扩大 K8s 调度器反对 AI 和大数据工作?》主题线上网络研讨会行将召开。 随着 Kubernetes 的广泛应用,越来越多的开发人员尝试应用 Kubernetes 运行和治理 Web 利用和微服务以外的工作负载。典型场景包含深度学习工作,高性能计算作业,基因计算工作流,甚至是传统的大数据处理工作。 围绕 Kubernetes 容器平台,对立治理各种异构算力资源,高效调度AI、大数据、高性能计算工作,未然成为云原生技术带来改革的畛域之一。 阿里云容器服务团队联合多年 Kubernetes 产品与客户反对教训,基于 Kubernetes scheduling framework 对调度器进行了大量扩大和改良,使其在多种场景下仍然能稳固、高效地调度简单工作负载类型,为用户应用 Kubernetes 同时治理在线利用和离线工作提供了根底技术撑持。 2020 年 7 月 15 日上午 10:00,《阿里巴巴如何扩大 K8s 调度器反对 AI 和大数据工作?》主题线上网络研讨会行将召开。 2020 年 7 月 15 日网研会邀你加入题目:阿里巴巴如何扩大 K8s 调度器反对 AI 和大数据工作?工夫:2020 年 7 月 15 日(10:00 AM)语言:中文 议题介绍本次研讨会将介绍 Kubernetes Scheduling Framework 的倒退现状,以及阿里云 Kubernetes 服务反对调度 AI、大数据等简单工作负载和 GPU 等异构计算资源的实践经验。还将具体介绍如何实现 Coscheduling/Gang Scheduling、Capacity Scheduling 等工作级调度个性。 ...

July 10, 2020 · 1 min · jiezi

详解k8s-4种类型Service

Services 和 PodsKubernetesPods是有生命周期的。他们可以被创建,而且销毁不会再启动。 如果您使用Deployment来运行您的应用程序,则它可以动态创建和销毁 Pod。 一个Kubernetes的Service是一种抽象,它定义了一组Pods的逻辑集合和一个用于访问它们的策略 - 有的时候被称之为微服务。一个Service的目标Pod集合通常是由[Label Selector](https://link.zhihu.com/?target=http%3A//kubernetes.kansea.com/docs/user-guide/labels/%23label-selectors) 来决定的(下面有讲一个没有选择器的Service 有什么用处)。 举个例子,想象一个处理图片的后端运行了三个副本。这些副本都是可以替代的 - 前端不关心它们使用的是哪一个后端。尽管实际组成后端集合的Pod可能会变化,前端的客户端却不需要知道这个变化,也不需要自己有一个列表来记录这些后端服务。Service抽象能让你达到这种解耦。 不像 Pod 的 IP 地址,它实际路由到一个固定的目的地,Service 的 IP 实际上不能通过单个主机来进行应答。 相反,我们使用 iptables(Linux 中的数据包处理逻辑)来定义一个虚拟IP地址(VIP),它可以根据需要透明地进行重定向。 当客户端连接到 VIP 时,它们的流量会自动地传输到一个合适的 Endpoint。 环境变量和 DNS,实际上会根据 Service 的 VIP 和端口来进行填充。 kube-proxy支持三种代理模式: 用户空间,iptables和IPVS;它们各自的操作略有不同。 Userspace作为一个例子,考虑前面提到的图片处理应用程序。 当创建 backend Service 时,Kubernetes master 会给它指派一个虚拟 IP 地址,比如 10.0.0.1。 假设 Service 的端口是 1234,该 Service 会被集群中所有的 kube-proxy 实例观察到。 当代理看到一个新的 Service, 它会打开一个新的端口,建立一个从该 VIP 重定向到新端口的 iptables,并开始接收请求连接。 当一个客户端连接到一个 VIP,iptables 规则开始起作用,它会重定向该数据包到 Service代理 的端口。 Service代理 选择一个 backend,并将客户端的流量代理到 backend 上。 ...

July 8, 2020 · 2 min · jiezi

Kubernetes-攻击矩阵

Kubernetes 攻击矩阵

July 3, 2020 · 1 min · jiezi

使用kubemark进行大规模Kubernetes集群性能测试

使用kubemark进行大规模Kubernetes集群性能测试

July 2, 2020 · 1 min · jiezi

how-to-set-up-kubemark

how to set up kubemark

July 2, 2020 · 1 min · jiezi

Kubernetes探秘配置文件目录结构

Kubernetes探秘—配置文件目录结构

July 2, 2020 · 1 min · jiezi

kubemark模拟k8s计算节点测试k8s组件性能

kubemark模拟k8s计算节点,测试k8s组件性能

July 2, 2020 · 1 min · jiezi

KubernetesK8s-安装使用kubeadm安装Kubernetes集群

Kubernetes(K8s) 安装(使用kubeadm安装Kubernetes集群)

July 1, 2020 · 1 min · jiezi

Kubernetes集群性能测试

Kubernetes集群性能测试

July 1, 2020 · 1 min · jiezi

在Kubernetes上集成Argo工作流和spark

在我的第一篇文章中,我谈到了Argo CD。这次是Argo Workflow,它又来自Argo项目,Kubernetes上的Spark,以及我们如何使两者一起工作。 Argo Workflow Argo Workflow是一个云原生工作流引擎,我们可以在其中编排具有任务序列的作业(工作流中的每个步骤都作为容器)。使用工作流定义,我们可以使用DAG捕获任务之间的依赖关系。替代Airflow?也许会!如果您正在寻找kubernetes的原生产品,我相信Argo Workflow不会让您失望。 将Argo工作流程部署到K8s(请为argo工作流程创建一个名称空间): 1. 安装 helm: curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3chmod 700 get_helm.sh./get_helm.sh2. 增加 argo repo 到 helm 并安装 helm repo add argo https://argoproj.github.io/argo-helmhelm repo updatehelm install argo-wf argo/argo -n argo-wf -f values.yaml在values.yaml中,您可以启用入口(如果集群中有入口控制器可用) ingress: enabled: true annotations: kubernetes.io/ingress.class: nginx kubernetes.io/tls-acme: “true” hosts: - argo.example.com您将立即部署并运行argo工作流程! Argo中的工作流程自动化由YAML模板驱动。 Argo提供了丰富的文档以及相关示例。如果您正在寻找自动化,我们甚至可以通过REST API提交工作流程。我不会在这里做太多深入的介绍,因为文档详细且经过了很好的解释。让我们继续下一个主题。 Spark on Kubernetes 从Spark 2.3开始,您可以使用Kubernetes运行和管理Spark资源。 Spark可以在Kubernetes管理的集群上运行。此功能使用已添加到Spark的原生Kubernetes调度程序。我们可以按需运行Spark驱动程序和执行程序Pod,这意味着没有专用的Spark集群。 有两种方法可以在Kubernetes上运行Spark:使用Spark-submit和Spark operator。 通过使用spark-submit CLI,您可以使用Kubernetes支持的各种配置选项提交Spark作业。 spark-submit spark-submit将作业提交委托给Kubernetes上的Spark driver pod,最后通过与Kubernetes API服务器通信来创建相关的Kubernetes资源。 ...

June 24, 2020 · 1 min · jiezi

簡單實用的Kubernetes-IDE-Lens

開箱 Lens、K8s IDE、K8s Dashboard,介紹使用在GKE以及Minikube

June 22, 2020 · 1 min · jiezi

Kubernetes集群性能测试

Kubernetes集群性能测试

June 22, 2020 · 1 min · jiezi

比官方K8S-Dashboard好用的桌面客户端Lens

比官方K8S Dashboard好用的桌面客户端:Lens

June 22, 2020 · 1 min · jiezi

Kubernetes中有状态应用的优雅缩容

将有状态的应用程序部署到Kubernetes是棘手的。 StatefulSet使它变得容易得多,但是它们仍然不能解决所有问题。最大的挑战之一是如何缩小StatefulSet而不将数据留在断开连接的PersistentVolume成为孤立对象上。在这篇博客中,我将描述该问题和两种可能的解决方案。 通过StatefulSet创建的每个Pod都有自己的PersistentVolumeClaim(PVC)和PersistentVolume(PV)。当按一个副本按比例缩小StatefulSet的大小时,其Pod之一将终止,但关联的PersistentVolumeClaim和绑定到其的PersistentVolume保持不变。在随后扩大规模时,它们会重新连接到Pod。 Scaling a StatefulSet 现在,想象一下使用StatefulSet部署一个有状态的应用程序,其数据在其pod中进行分区。每个实例仅保存和处理一部分数据。当您缩小有状态应用的规模时,其中一个实例将终止,其数据应重新分配到其余的Pod。如果您不重新分配数据,则在再次进行扩展之前,它仍然不可访问。 Redistributing data on scale-down 在正常关机期间重新分发数据您可能会想:“既然Kubernetes支持Pod正常关闭的机制,那么Pod是否可以在关闭过程中简单地将其数据重新分配给其他实例呢?”事实上,它不能。为什么不这样做有两个原因: Pod(或更确切地说,其容器)可能会收到除缩容以外的其他原因的终止信号。容器中运行的应用程序不知道为什么终止该程序,因此不知道是否要清空数据。即使该应用程序可以区分是缩容还是由于其他原因而终止,它也需要保证即使经过数小时或数天也可以完成关闭程序。 Kubernetes不提供该保证。如果应用程序进程在关闭过程中死掉,它将不会重新启动,因此也就没有机会完全分发数据。因此,相信在正常关闭期间Pod能够重新分发(或以其他方式处理其所有数据)并不是一个好主意,并且会导致系统非常脆弱。 使用 tear-down 容器?如果您不是Kubernetes的新手,那么你很可能知道什么是初始化容器。它们在容器的主要容器之前运行,并且必须在主要容器启动之前全部完成。 如果我们有tear-down容器(类似于init容器),但是在Pod的主容器终止后又会运行,该怎么办?他们可以在我们的有状态Pod中执行数据重新分发吗? 假设tear-down容器能够确定Pod是否由于缩容而终止。并假设Kubernetes(更具体地说是Kubelet)将确保tear-down容器成功完成(通过在每次返回非零退出代码时重新启动它)。如果这两个假设都成立,我们将拥有一种机制,可确保有状态的容器始终能够按比例缩小规模重新分配其数据。 但是? 可悲的是,当tear-down容器本身发生瞬态错误,并且一次或多次重新启动容器最终使它成功完成时,像上述的tear-down容器机制将只处理那些情况。但是,在tear-down过程中托管Pod的集群节点死掉的那些不幸时刻又如何呢?显然,该过程无法完成,因此无法访问数据。 现在很明显,我们不应该在Pod关闭时执行数据重新分配。相反,我们应该创建一个新的Pod(可能安排在一个完全不同的集群节点上)以执行重新分发过程。 这为我们带来了以下解决方案: 缩小StatefulSet时,必须创建一个新的容器并将其绑定到孤立的PersistentVolumeClaim。我们称其为“_drain pod_”,因为它的工作是将数据重新分发到其他地方(或以其他方式处理)。Pod必须有权访问孤立的数据,并且可以使用它做任何想做的事情。由于每个应用程序的重新分发程序差异很大,因此新的容器应该是完全可配置的-用户应该能够在drain Pod内运行他们想要的任何容器。 StatefulSet Drain Controller由于StatefulSet控制器当前尚不提供此功能,因此我们可以实现一个额外的控制器,其唯一目的是处理StatefulSet缩容。我最近实现了这种控制器的概念验证。您可以在GitHub上找到源代码: luksa/statefulset-scaledown-controllergithub.com 下面我们解释一下它是如何工作的。 在将控制器部署到Kubernetes集群后,您只需在StatefulSet清单中添加注释,即可将drain容器模板添加到任何StatefulSet中。这是一个例子: apiVersion: apps/v1kind: StatefulSetmetadata: name: datastore annotations: statefulsets.kubernetes.io/drainer-pod-template: | { "metadata": { "labels": { "app": "datastore-drainer" } }, "spec": { "containers": [ { "name": "drainer", "image": "my-drain-container", "volumeMounts": [ { "name": "data", "mountPath": "/var/data" } ] } ] } }spec: ...该模板与StatefulSet中的主要Pod模板没有太大区别,只不过它是通过注释定义的。您可以像平常一样部署和扩展StatefulSet。 ...

June 22, 2020 · 1 min · jiezi

延迟应用启动直到Sidecar准备就绪

Kubernetes在Pod中启动容器的方式出乎意料。在检查了源代码以确认我所看到的内容之后,我意识到我刚刚找到了Istio Service Mesh中一个长期存在的问题的解决方案。 我相信大多数Kubernetes用户都假定Pod的初始化容器完成后,将并行启动Pod的常规容器。事实并非如此。 如果检查启动容器的Kubelet代码,则会注意到它是按顺序执行的。该代码在一个线程中执行,并按照容器在pod的spec.containers数组中列出的顺序启动容器。 // Step 7: start containers in podContainerChanges.ContainersToStart. for _, idx := range podContainerChanges.ContainersToStart { start("container", containerStartSpec(&pod.Spec.Containers[idx])) }但是,假设容器镜像已经存储在本地,则在Kubelet启动第一个容器之后,Kubelet启动第二个容器所花费的时间可以忽略不计。实际上,它们都是同时启动的。 当一个容器依赖于另一个容器并要求它完全启动才能运行时,这是不理想的。 Istio Proxy sidecar容器就是一个例子。由于应用程序的传出通信是通过代理路由的,因此在启动应用程序本身之前,代理必须已启动并正在运行。 您可以在应用程序容器中添加一个Shell脚本,以等待代理启动,然后运行该应用程序的可执行文件。但这需要更改应用程序本身。理想情况下,我们希望在不对应用程序或其容器镜像进行任何更改的情况下将代理注入Pod。 事实证明,这可以通过利用Kubernetes中的同步容器启动来完成。 首先,我们需要将代理指定为spec.containers中的第一个容器,但这只是解决方案的一部分,因为它只能确保首先启动代理容器,而不会等待其准备就绪。其他容器立即启动,从而导致容器之间的竞争状态。我们需要防止Kubelet在代理准备好之前启动其他容器。 这是启动后生命周期钩子出现的地方。事实证明,启动容器的Kubelet代码会阻止下一个容器的启动,直到启动后处理程序终止为止。 我们可以利用这种行为。不仅在Istio中,而且在必须启动Sidecar容器并准备就绪的每个Pod中,应用程序容器才能启动。 简而言之,Sidecar启动问题的解决方案如下: 如果sidecar容器提供了一个等待该sidecar就绪的可执行文件,则可以在容器的启动后挂钩中调用该文件,以阻止pod中其余容器的启动。 下图应该可以帮助您直观地看到容器中发生的情况。 具体yaml如下: apiVersion: v1kind: Podmetadata: name: sidecar-starts-firstspec: containers: - name: sidecar image: my-sidecar lifecycle: postStart: exec: command: - /bin/wait-until-ready.sh - name: application image: my-application但是,这种方法并不完美。如果在启动后挂钩中调用的命令或容器的主进程失败,则其他容器将立即启动。尽管如此,在Kubernetes引入对sidecar container的适当支持之前,这应该是一个好的解决方法。或者直到有人决定更改Kubelet的行为,并使其在单独的goroutine中启动容器。 尽管此技术可以解决容器启动顺序的问题,但是当您删除容器时,容器的容器停止顺序却无济于事。Pod的容器实际上是并行终止的。当它关闭一个Pod时,Kubelet在goroutine中执行容器终止代码-每个容器一个。与启动后挂钩不同,停止前挂钩因此并行运行。 如果仅在主应用程序容器终止后才需要停靠sidecar,则必须以其他方式处理。 PS: 本文属于翻译,原文

June 21, 2020 · 1 min · jiezi

k8s-部署生产vault集群

在之前的文章中,我们在k8s中部署了consul 生产集群。今天我继续在k8s中部署一个vault的生产集群。 Vault可以在高可用性(HA)模式下运行,以通过运行多个Vault服务器来防止中断。Vault通常受存储后端的IO限制的约束,而不是受计算要求的约束。某些存储后端(例如Consul)提供了附加的协调功能,使Vault可以在HA配置中运行,而其他一些则提供了更强大的备份和还原过程。 在高可用性模式下运行时,Vault服务器具有两个附加状态:备用和活动状态。在Vault群集中,只有一个实例将处于活动状态并处理所有请求(读取和写入),并且所有备用节点都将请求重定向到活动节点。 部署 我们的consul 集群复用之前文章中部署的consul集群。 vault配置文件server.hcl如下: listener "tcp" { address = "0.0.0.0:8200" cluster_address = "POD_IP:8201" tls_disable = "true"}storage "consul" { address = "127.0.0.1:8500" path = "vault/"}api_addr = "http://POD_IP:8200"cluster_addr = "https://POD_IP:8201"接下我们创建configmap: kubectl create configmap vault --from-file=server.hcl大家可以注意到配置文件中的POD_IP,我们将会在容器启动的时候,sed替换成真实的pod的IP。我们采用StatefulSet方式部署一个两个节点的vault集群。通过sidecar的方式将consul client agent和vault部署到一个Pod中。 apiVersion: apps/v1kind: StatefulSetmetadata: name: vault labels: app: vaultspec: serviceName: vault podManagementPolicy: Parallel replicas: 3 updateStrategy: type: OnDelete selector: matchLabels: app: vault template: metadata: labels: app: vault spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - consul topologyKey: kubernetes.io/hostname podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - vault topologyKey: kubernetes.io/hostname containers: - name: vault command: - "/bin/sh" - "-ec" args: - | sed -E "s/POD_IP/${POD_IP?}/g" /vault/config/server.hcl > /tmp/server.hcl; /usr/local/bin/docker-entrypoint.sh vault server -config=/tmp/server.hcl image: "vault:1.4.2" imagePullPolicy: IfNotPresent securityContext: capabilities: add: - IPC_LOCK env: - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP - name: VAULT_ADDR value: "http://127.0.0.1:8200" - name: VAULT_API_ADDR value: "http://$(POD_IP):8200" - name: SKIP_CHOWN value: "true" volumeMounts: - name: vault-config mountPath: /vault/config/server.hcl subPath: server.hcl ports: - containerPort: 8200 name: vault-port protocol: TCP - containerPort: 8201 name: cluster-port protocol: TCP readinessProbe: # Check status; unsealed vault servers return 0 # The exit code reflects the seal status: # 0 - unsealed # 1 - error # 2 - sealed exec: command: ["/bin/sh", "-ec", "vault status -tls-skip-verify"] failureThreshold: 2 initialDelaySeconds: 5 periodSeconds: 3 successThreshold: 1 timeoutSeconds: 5 lifecycle: # Vault container doesn't receive SIGTERM from Kubernetes # and after the grace period ends, Kube sends SIGKILL. This # causes issues with graceful shutdowns such as deregistering itself # from Consul (zombie services). preStop: exec: command: [ "/bin/sh", "-c", # Adding a sleep here to give the pod eviction a # chance to propagate, so requests will not be made # to this pod while it's terminating "sleep 5 && kill -SIGTERM $(pidof vault)", ] - name: consul-client image: consul:1.7.4 env: - name: GOSSIP_ENCRYPTION_KEY valueFrom: secretKeyRef: name: consul key: gossip-encryption-key - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP args: - "agent" - "-advertise=$(POD_IP)" - "-config-file=/etc/consul/config/client.json" - "-encrypt=$(GOSSIP_ENCRYPTION_KEY)" volumeMounts: - name: consul-config mountPath: /etc/consul/config - name: consul-tls mountPath: /etc/tls lifecycle: preStop: exec: command: - /bin/sh - -c volumes: - name: vault-config configMap: defaultMode: 420 name: vault - name: consul-config configMap: defaultMode: 420 name: consul-client - name: consul-tls secret: secretName: consul如果你的k8s集群pod网段flat,可以和vpc当中的主机互相访问。那么按照以上的配置即可。否则需要设置pod的hostNetwork: true。查看部署情况: ...

June 21, 2020 · 4 min · jiezi

为什么k8s被叫做容器编排器

先吐槽一下: sf的编辑器好奇怪,对yaml代码的md支持不好。我放弃了,斗不过sf的这个代码编辑器。。。看来文章和评论的编辑器一样,同样对yaml支持不友好不能说是docker的编排工具,应该说是对“容器”的编排工具,docker只是一种容器实现方式 “编排”,通俗理解,类似我国以前大学生毕业后工作“包分配”,大学生毕业后,根据事业单位的特点和大学生的专业和特长信息,看看他们应该安排到哪个单位合适。 一般我们一个集群的会有“多台物理机器”,每个物理机器又可以跑“多个容器”,但是到底哪个容器应该跑在哪些物理机里面,就要有一套规则规划,k8s就是实现了这样一套规则。 简单举个几个例子,k8s的这些规则里面有比如“节点选择”,“节点亲和性”、“pod亲和性”等 节点选择比如下面这个这个规则,我们希望nginx安排跑在有ssd类型硬盘的物理机器上 apiVersion: v1kind: Podmetadata: name: nginx labels: env: testspec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: disktype: ssd节点亲和性如下面这个例子,我们希望: 比如 192.168.1.140和 192.168.1.161 不要给我跑pod,area=south如的这个果有节点满足area=south的这个条件的话,pod尽量往这里安排。 apiVersion: v1kind: Pod...spec: containers: name: with-node-affinity image: nginxaffinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: NotIn values: - 192.168.1.140 - 192.168.1.161 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: area operator: In values: - south# pod亲和性如下面这例子,我们希望:1. 我们希望这个pod和有`app=busybox-pod`这个标签信息的pod,尽量分配到一起2. 同时,不希望这个pod和有`app=node-affinity-pod`的这些pod尽量不要搞到一起。apiVersion: v1kind: Pod...spec: containers: ...

June 20, 2020 · 1 min · jiezi

使用水平Pod自动缩放器在Kubernetes上自动缩放应用程序

本文概述了Kubernetes中的Horizontal Pod Autoscaler(HPA)的工作方式以及使用方法。 介绍部署具有静态配置的副本数的无状态应用不是最佳选择。 而弹性副本数目具备以下特点: 当请求率增加时,应用程序应扩大规模(即增加副本数)以保持响应速度。当请求率降低时,应用程序应缩小规模(即减少副本数),以避免浪费资源。在水平缩放的情况下,放大也称为“_scaling out_”,而缩小也称为“_scaling in_”。这与垂直缩放(请参见下文)形成对比,垂直缩放仅使用术语“按比例放大”和“按比例缩小”。借助Horizontal Pod Autoscaler(HPA),Kubernetes以上述方式为自动缩放应用程序提供了出色的支持。 Kubernetes中不同类型的自动伸缩首先,为消除任何误解,让我们澄清一下Kubernetes中术语“自动缩放”的用法。 Kubernetes包括几个自动缩放功能: Horizontal Pod Autoscaler (HPA): 调整应用程序副本Pod的数量(水平缩放)Vertical Pod Autoscaler (VPA): 调整资源请求和应用程序容器的限制(垂直缩放)Cluster Autoscaler: 调整集群的节点数这些自动缩放器彼此完全独立,并且都使用不同的概念和机制。 本文专门讨论Horizontal Pod Autoscaler。 什么是Horizontal Pod Autoscaler?Horizontal Pod Autoscaler(HPA)是内置的Kubernetes功能,它允许根据一个或多个默认或用户定义的指标来水平缩放应用程序。 水平缩放意味着增加和减少副本数量。垂直缩放意味着增加和减少单个副本的计算资源。从技术上讲,HPA是一个Kubernetes控制器,用于跟踪HorizontalPodAutoscaler资源并由其配置。 HPA持续监视有关一个应用程序的一个或多个指标,并调整此应用程序的副本数,以使指标尽可能接近指定的目标值。 HPA可以使用scale子资源来扩展所有这些Kubernetes资源,其中包括Deployment,StatefulSet和ReplicaSet。HPA执行的控制循环如下所示: 控制循环的步骤为: 查询缩放指标计算所需的副本数将应用程序缩放到所需数量的副本默认情况下,此控制循环每15秒执行一次。所需副本数的计算基于缩放指标和这些指标的用户提供的目标值。 在控制循环的每次迭代中,HPA都会计算出一个副本计数,该副本计数将使度量的测量值尽可能接近目标值。 例如,假设缩放指标是应用程序所有副本Pod每秒平均接收的请求数(req/sec): 如果目标值为10 req / sec,当前值为20 req / sec,则应用程序过载,并且HPA必须扩大应用程序的规模(即增加副本数),以使度量标准减小并接近目标值。如果目标值为10 req / sec,当前值为2 req / sec,则该应用程序未充分利用,因此HPA必须缩小该应用程序的比例(即减少副本数),以使度量标准提高并更加接近目标值。用于计算所需副本数的算法基于以下公式: X = N * (c/t)解读: X 是期望的副本数N 是当前的副本数c 伸缩指标的当前值t 伸缩指标的目前值这就是HPA的总体运作方式-现在让我们看一下它的配置方式。 如何配置Horizontal Pod Autoscaler?通过HorizontalPodAutoscaler资源完成HPA的配置。 HorizontalPodAutoscaler资源可以指定以下信息: ...

June 18, 2020 · 1 min · jiezi

分享一份阿里云内部超全K8s实战手册免费下载

一直关注云计算领域的人,必定知道Docker和Kubernetes的崛起。如今,世界范围内的公有云巨头(谷歌、亚马逊、微软、华为云、阿里云等等)都在其传统的公共云服务之上提供托管的Kubernetes服务。Kubernetes功能强大、扩展性高,在许多人看来,它正在成为云计算的终极解决方案。 接下来本文将为大家免费提供阿里云《深入浅出Kubernetes项目实战手册》下载,帮助你一次搞懂 6 个核心原理,吃透基础理论,一次学会 6 个典型问题的华丽操作! 如何免费下载 扫码,发送"阿里云",即可免费获得 ▲持续关注 获取更多免费福利 理论和实践的完美契合 技术细节追根究底 阿里云真实案例的沉淀 理论阐述深入浅出 本书作者罗建龙(花名声东),阿里云技术专家,有着多年操作系统和图形显卡驱动调试和开发经验。目前专注云原生领域,容器集群和服务网格。本书分为理论篇和实践篇,共汇集了 12 篇技术文章,深入解析了集群控制、集群伸缩原理、镜像拉取等理论,带你实现从基础概念的准确理解到上手实操的精准熟练,深入浅出使用 Kubernetes!

June 18, 2020 · 1 min · jiezi

使用Open-Policy-Agent实现Kubernetes-Pod安全策略

Kubernetes是当今云原生生态系统中最受欢迎的容器编排平台。因此,Kubernetes的安全性也引起了越来越多的关注。 在此博客文章中,首先我将讨论Pod安全策略准入控制器。然后,我们将看到Open Policy Agent如何实现Pod安全策略。实际上,Open Policy Agent被视为Pod安全策略的潜在替代方案。 首先,简要介绍一下容器,安全性和准入控制器。 容器和安全简介容器轻巧,轻便且易于管理。在同一主机上运行的容器没有单独的物理/虚拟机。换句话说,容器共享运行它们的主机的资源,硬件和OS内核。因此,具有适当的安全性变得非常重要,这些安全性涉及容器中可以运行哪些进程,这些进程具有哪些特权,容器是否将允许特权升级,使用了什么镜像等等。 Pod是Kubernetes应用程序的基本执行单元,是您创建或部署的Kubernetes对象模型中最小和最简单的单元。它是一个或多个具有共享存储/网络的容器的组,以及有关如何运行容器的规范。因此,在容器上实施安全策略时,我们将检查安全策略并将其应用于Pod规范。那么,这些策略如何执行?使用准入控制器。 什么是Admission Controllers?准入控制器是kube-apiserver的一部分。在配置存储在集群设置(etcd)中之前,它们拦截对Kubernetes API服务器的请求。准入控制器可以是正在验证(用于验证传入请求的一个)或正在变异(用于修改传入请求的一个)或两者都在进行。请参阅Kubernetes文档以快速浏览各种准入控制器。 Open Policy Agent 作为 admission controllerOpen Policy Agent(OPA)是一种开放源代码的通用策略引擎,可以将策略编写为代码。 OPA提供了一种高级声明性语言-Rego-以策略作为代码。使用OPA,我们可以跨微服务,CI / CD管道,API网关等执行策略。 OPA最重要的用例之一是Kubernetes作为准入控制者的策略实施。 OPA作为准入控制器,您可以强制执行非root用户之类的策略,要求使用特定的资源标签,确保所有pod都指定了资源请求和限制等。基本上,OPA允许您使用Rego语言将任何自定义策略编写为代码。 这些策略以Rego编写并加载到OPA中,作为Kubernetes集群上的准入控制器运行。 OPA将根据Rego策略评估对Kubernetes API服务器的任何资源创建/更新/删除请求。如果请求满足所有策略,则允许该请求。但是,即使单个策略失败,请求也会被拒绝。 在此处阅读有关OPA,Rego的更多信息,并用作OPA文档中的准入控制器。 Pod Security PolicyPod安全策略(PSP)是实现为准入控制器的集群级别资源。 PSP允许用户将安全要求转换为管理Pod规范的特定策略。首先,创建PodSecurityPolicy资源时,它什么也不做。为了使用它,必须通过允许“使用”动词来授权请求用户或目标pod的服务帐户使用该策略。您可以参考Kubernetes文档上的启用Pod安全策略。 注意,PSP准入控制器既充当验证角色,又充当变异准入控制器。对于某些参数,PSP准入控制器使用默认值来更改传入的请求。此外,顺序始终是先突变然后验证。 使用PSP我们可以控制哪些所有参数?下表简要概述了PSP中使用的各种参数和字段。在此处的Kubernetes文档中提供了详细说明。 那么,我们可以在OPA中实现PSP吗?前面提到,Rego语言允许我们将任何自定义策略编写为代码。这意味着,我们可以使用Rego编写上述的Pod安全策略,并以OPA作为准入控制器来执行。 让我们快速了解一下实施“特权”Pod安全策略的Rego策略。可以在Rego playground试用此策略。 package kubernetes.admissiondeny[message] { #applies for Pod resources input.request.kind.kind == "Pod" #loops through all containers in the request container := input.request.object.spec.containers[_] #for each container, check privileged field container.securityContext.privileged #if all above statements are true, return message message := sprintf("Container %v runs in privileged mode.", [container.name])}那么,该策略有何作用?如果输入请求中的任何容器正在作为特权容器运行,它将返回一条消息。 ...

June 10, 2020 · 1 min · jiezi

Linkerd-28简单安全的多集群Kubernetes服务网格

我们很高兴宣布Linkerd 2.8的发布!该版本为Linkerd引入了一个新的多集群扩展,使它可以跨Kubernetes集群建立连接,这些集群对应用程序而言是安全的,透明的,并且可以与任何网络拓扑一起使用。我们认为,这是当今提供安全的Kubernetes多集群连接的最简单选择。 2.8版本还使Linkerd在附加系统的开头有了更多的模块化,并引入了许多其他功能和稳定性改进。 Multi-cluster KubernetesLinkerd 2.8的新多集群功能意味着Linkerd现在可以安全,对应用程序完全透明且独立于网络拓扑的方式跨集群边界连接Kubernetes服务。正如我们之前的文章中所讨论的,此多集群功能旨在满足一些关键目标: 提供统一的信任域。源工作负载和目标工作负载的身份必须在群集边界内和跨群集边界的每一步进行验证。分离故障域。群集中断仍应允许其余群集正常运行。支持异构网络。由于群集可以跨越云,VPC,本地数据中心及其组合,因此Linkerd除网关连接性外,不应引入任何L3 / L4要求。提供具有集群内通信的统一模型。 Linkerd为群集内通信提供的可观察性,可靠性和安全性功能应扩展到这种新的跨群集通信。就像集群内连接一样,Linkerd的跨集群连接对应用程序代码也是透明的。cluster _west_的服务A可以通过直接将其寻址为C.east或将其寻址为C并让Linkerd自动将该服务的流量路由(甚至转移一部分)到集群C,以与集群C的服务C对话。东向集群。不管该通信是在集群内,在数据中心或VPC内的跨集群还是在公共Internet上进行,Linkerd都将在集群之间建立连接,并通过mTLS在两侧进行加密和认证。 这项新的多集群功能可为Linkerd解锁大量用例,包括故障转移(在出现故障时跨数据中心或云转换流量); “反向多租户”(每个租户都有自己的集群);混合云(工作负载可以在本地环境和云环境之间移动,而不会影响应用程序的其余部分)。 最后,像Linkerd的所有功能一样,Linkerd的多集群“服务镜像”方法会尽可能利用现有的Kubernetes功能,并最少增加额外的设备。远程服务直接表示为Kubernetes服务;没有引入新的CRD;并且配置复杂度保持在最低限度。 Ambassador 支持 Multi-cluster我们很高兴地报告,我们在Ambassador项目中的朋友已经创建了一个多集群集成,使Ambassador用户可以利用Ambassador部署作为Linkerd的多集群网关!在Ambassador博客文章中了解更多信息。 附加组件2.8版本还引入了一个简单的附加系统,用于从Linkerd添加(或删除)功能包。 Linkerd 2.8附带两个插件: 一个Jaeger插件,它添加Jaeger和oc-collector组件以收集和显示分布式跟踪到您的集群一个Grafana插件(默认情况下启用),可将Grafana图添加到Linkerd的仪表板。将来,我们将把更多功能转移到附加组件中,例如,您可以删除默认的Prometheus安装,然后用自己的安装替换,也可能完全不用。 其他Linkerd 2.8还提供了大量其他改进,性能增强和错误修复的列表,其中包括: Helm图表更加灵活和模块化,带有新的Prometheus配置选项。代理现在使用pod元数据标记发出的分布式跟踪范围。代理的各种性能改进,以减少争用,改善延迟并减少虚假超时。自动防止常见的流量环流情况。有关详细信息,请参见完整的发行说明。 Linkerd的规划我们相信Linkerd的核心价值是连通性-在云原生世界中,连通性不仅仅意味着“ A和B可以交换数据包”,而是“ A和B可以以验证双方身份的方式交换数据包”侧面具有清晰的授权语义;对第三方保密;并且是可测量和可检查的”。 展望未来,我们看到Linkerd能够创建此连接,从而将其转换为适用于您的Kubernetes下文的安全平面。 2.8版本标志着朝着这个方向迈出了一大步,接下来的几个版本将充实Linkerd的功能集,包括将mTLS扩展到所有连接。引进政策;以及更多。请继续关注有关此主题的更多信息。 立即体验准备尝试Linkerd了吗?那些通过我们每周的边缘发布跟踪2.x分支的人将已经看到这些功能的实际应用。无论哪种方式,都可以通过运行以下命令下载稳定的2.8版本: curl https://run.linkerd.io/install | sh使用Helm?请参阅我们的有关在Helm中安装Linkerd的指南。从以前的版本升级?我们为您提供了覆盖:请参阅我们的Linkerd升级指南,以了解如何使用linkerd upgrade命令。 PS:本文属于翻译,原文

June 10, 2020 · 1 min · jiezi

Consul-on-Kubernetes

consul 发展到今日,早已不是只用于服务发现和配置共享的工具了。官方对其的定义是自动化网络配置,发现服务并启用跨任何云或运行时的安全连接。 特性与Kubernetes集成和扩展。利用Helm在Kubernetes上快速部署Consul。自动为Kubernetes资源注入sidecar。将多个集群联合到一个服务网格中。跨任何运行时的服务网格。在任何运行时或基础架构中跨任何云在裸机,虚拟机和Kubernetes集群中部署服务网格。 动态的负载均衡。通过集成的DNS解决发现的服务。自动化第三方负载均衡器(F5,NGINX,HAProxy)。无需手动配置网络设备。安全的多云服务网络。利用访问策略和服务网格资源之间的自动mTLS加密,在任何环境中运行的安全服务。 通过运行状况检查发现服务。Consul支持检测新服务的部署,对现有服务的更改,并提供实时代理运行状况以减少停机时间。强大的生态系统。Consul为许多流行的DevOps和网络工具提供支持并与之集成。默认端口consul 默认使用下列端口 8300(tcp): Server RPC,server 用于接受其他 agent 的请求8301(tcp,udp): Serf LAN,数据中心内 gossip 交换数据用8302(tcp,udp): Serf WAN,跨数据中心 gossip 交换数据用8400(tcp): CLI RPC,接受命令行的 RPC 调用8500(tcp): HTTP API 及 Web UI8600(tcp udp): DNS 服务,可以把它配置到 53 端口来响应 dns 请求部署官方推荐的helm部署方案,包括了诸多解决方案。当我们只是用来做服务发现或是配置中心的时候,我们可以选择yaml部署。 本文将完成在Kubernetes上部署三(3)节点Consul集群。 使用StatefulSet的三(3)个节点Consul群集使用TLS和加密密钥的Consul成员之间的安全通信生成 TLS Certificates新建ca目录,包含以下三个文件: ca-config.json { "signing": { "default": { "expiry": "43800h" }, "profiles": { "default": { "usages": ["signing", "key encipherment", "server auth", "client auth"], "expiry": "43800h" } } }}ca-csr.json ...

June 10, 2020 · 3 min · jiezi

记一次-K8S-内部服务调用域名解析超时排坑经历

前言近期线上 k8s 时不时就会出现一些内部服务间的调用超时问题,通过日志可以得知超时的原因都是出现在域名解析上,并且都是 k8s 内部的域名解析超时,于是直接先将内部域名替换成 k8s service 的 IP,观察一段时间发现没有超时的情况发生了,但是由于使用 service IP 不是长久之计,所以还要去找解决办法。 复现一开始运维同事在调用方 pod 中使用ab工具对目标服务进行了多次压测,并没有发现有超时的请求,我介入之后分析ab这类 http 压测工具应该都会有 dns 缓存,而我们主要是要测试 dns 服务的性能,于是直接动手撸了一个压测工具只做域名解析,代码如下: package mainimport ( "context" "flag" "fmt" "net" "sync/atomic" "time")var host stringvar connections intvar duration int64var limit int64var timeoutCount int64func main() { // os.Args = append(os.Args, "-host", "www.baidu.com", "-c", "200", "-d", "30", "-l", "5000") flag.StringVar(&host, "host", "", "Resolve host") flag.IntVar(&connections, "c", 100, "Connections") flag.Int64Var(&duration, "d", 0, "Duration(s)") flag.Int64Var(&limit, "l", 0, "Limit(ms)") flag.Parse() var count int64 = 0 var errCount int64 = 0 pool := make(chan interface{}, connections) exit := make(chan bool) var ( min int64 = 0 max int64 = 0 sum int64 = 0 ) go func() { time.Sleep(time.Second * time.Duration(duration)) exit <- true }()endD: for { select { case pool <- nil: go func() { defer func() { <-pool }() resolver := &net.Resolver{} now := time.Now() _, err := resolver.LookupIPAddr(context.Background(), host) use := time.Since(now).Nanoseconds() / int64(time.Millisecond) if min == 0 || use < min { min = use } if use > max { max = use } sum += use if limit > 0 && use >= limit { timeoutCount++ } atomic.AddInt64(&count, 1) if err != nil { fmt.Println(err.Error()) atomic.AddInt64(&errCount, 1) } }() case <-exit: break endD } } fmt.Printf("request count:%d\nerror count:%d\n", count, errCount) fmt.Printf("request time:min(%dms) max(%dms) avg(%dms) timeout(%dn)\n", min, max, sum/count, timeoutCount)}编译好二进制程序直接丢到对应的 pod 容器中进行压测: ...

June 9, 2020 · 5 min · jiezi

细数k8s支持的4种类型的container

截止目前k8s1.18,k8s已经支持标准容器,sidecar容器,init 容器,ephemeral 容器 4种类型的containers。本文我们详细介绍一下这4种容器的特性已经使用场景。 Ephemeral 容器临时容器与其他容器的不同之处在于,它们缺少对资源或执行的保证,并且永远不会自动重启,因此不适用于构建应用程序。临时容器使用与常规容器相同的 ContainerSpec 段进行描述,但许多字段是不相容且不允许的。 临时容器没有端口配置,因此像 ports,livenessProbe,readinessProbe 这样的字段是不允许的。Pod 资源分配是不可变的,因此 resources 配置是不允许的。有关允许字段的完整列表,请参见临时容器参考文档。临时容器是使用 API 中的一种特殊的 ephemeralcontainers 处理器进行创建的,而不是直接添加到 pod.spec 段,因此无法使用 kubectl edit 来添加一个临时容器。 与常规容器一样,将临时容器添加到 Pod 后,将不能更改或删除临时容器。 为什么我们需要Ephemeral 容器? 我们知道容器的优点是它们通过使用不变方法提供所有必需的依赖项来运行隔离的进程。通过仅将所需的依赖项添加到镜像中,容器可以降低攻击面并提供更快的启动和部署。使用“distroless”方法构建容器镜像(基于scratch),通过仅包含已编译的应用程序二进制文件,将容器镜像提升到了一个新的水平。与普通的容器镜像不同,它们不基于任何种类的Linux发行版,因此不包含任何其他可通过kubectl exec执行以进行故障排除的二进制文件和工具。这就决定了该容器有助于提供安全可靠的运行时环境,但也很难在问题发生时进行调试。 在这种情况下,临时容器发挥作用。它们实现了调试容器附加到主进程的功能,然后你可以用于调试任何类型的问题。调试容器可以基于任何镜像,因此可以根据您的需求进行定制。您可以构建自己的调试镜像,其中包含特殊的调试二进制文件或仅包含curl,OpenSSL和MongoDB客户端之类的工具。但是,您也可以选择Linux发行版(如Ubuntu)或仅运行Busybox镜像,这两个镜像都已经包含了许多有用的工具。 如何使用临时容器? 临时容器是alpha功能,因此默认情况下处于禁用状态。您将需要激活以下功能门才能使用它们: 临时容器PodShareProcessNamespace(v1.16中的beta版,因此默认情况下已启用)本节中的示例演示了临时容器如何出现在 API 中。 通常,您可以使用 kubectl 插件进行故障排查,从而自动化执行这些步骤。 临时容器是使用 Pod 的 ephemeralcontainers 子资源创建的,可以使用 kubectl --raw 命令进行显示。首先描述临时容器被添加为一个 EphemeralContainers 列表: { "apiVersion": "v1", "kind": "EphemeralContainers", "metadata": { "name": "example-pod" }, "ephemeralContainers": [{ "command": [ "sh" ], "image": "busybox", "imagePullPolicy": "IfNotPresent", "name": "debugger", "stdin": true, "tty": true, "terminationMessagePolicy": "File" }]}使用如下命令更新已运行的临时容器 example-pod: ...

June 7, 2020 · 2 min · jiezi

Kubernetes本地持久化方案

Kubernetes中的本地存储意味着在每个节点服务器上本地可用的存储设备或文件系统。本文介绍Kubernetes中现有的本地存储解决方案,包括官方原生支持的存储方式以及社区的一些常见方案。 目前官方支持以下3种本地存储方式: emptyDirhostPathLocal Persistent VolumeemptyDir当 Pod 指定到某个节点上时,首先创建的是一个emptyDir卷,并且只要 Pod 在该节点上运行,卷就一直存在。 就像它的名称表示的那样,卷最初是空的。 尽管 Pod 中的容器挂载emptyDir卷的路径可能相同也可能不同,但是这些容器都可以读写emptyDir卷中相同的文件。 当 Pod 因为某些原因被从节点上删除时,emptyDir卷中的数据也会永久删除。 注意:容器崩溃并不会导致 Pod 被从节点上移除,因此容器崩溃时 `emptyDir` 卷中的数据是安全的。emptyDir 的一些用途: 缓存空间,例如基于磁盘的归并排序。为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。默认情况下, emptyDir 卷存储在支持该节点所使用的介质上;这里的介质可以是磁盘或 SSD 或网络存储,这取决于您的环境。 但是,您可以将 emptyDir.medium 字段设置为 "Memory",以告诉 Kubernetes 为您安装 tmpfs(基于 RAM 的文件系统)。 虽然 tmpfs 速度非常快,但是要注意它与磁盘不同。 tmpfs 在节点重启时会被清除,并且您所写入的所有文件都会计入容器的内存消耗,受容器内存限制约束。 emptyDir的位置应该在运行pod的给定节点上的/var/lib/kubelet/pods/{podid}/volumes/kubernetes.io~empty-dir/ 目录下。 Pod 示例apiVersion: v1kind: Podmetadata: name: my-podspec: containers: - image: my-app-image name: my-app volumeMounts: - mountPath: /cache name: cache-volume volumes: - name: cache-volume emptyDir: {}Pod中的所有容器共享使用emptyDir卷。因此,我们使用emptyDir的一个场景是,Pod中init容器负责到配置中心或是秘钥管理中心拉取一些配置,然后写入到emptyDir中,这样业务容器就可以读取到配置。hostPathhostPath卷能将主机节点文件系统上的文件或目录挂载到您的 Pod 中。 虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大的逃逸机会。 ...

June 7, 2020 · 2 min · jiezi

Pod多网卡方案MULTUS

在Kubernetes中,网络是非常重要的一个领域。 Kubernetes本身不提供网络解决方案,但是提供了CNI规范。这些规范被许多CNI插件(例如WeaveNet,Flannel,Calico等)遵守。这些插件中任何一个都可以在集群上使用和部署以提供网络解决方案。该网络称为集群的默认网络。此默认网络使Pods不仅可以在同一节点上而且可以在群集中的各个节点之间相互通信。 随着发展,Kubernetes 缺乏支持VNF中多个网络接口的所需功能。传统上,网络功能使用多个网络接口分离控制,管理和控制用户/数据的网络平面。他们还用于支持不同的协议,满足不同的调整和配置要求。 为了解决这个需求,英特尔实现了MULTUS的CNI插件,其中提供了将多个接口添加到Pod的功能。这允许POD通过不同的接口连接到多个网络,并且每个接口都将使用其自己的CNI插件(CNI插件可以相同或不同。这完全取决于需求和实现)。 下面是Multus CNI提供的连接到Pod的网络接口的图示。该图显示了具有三个接口的容器:eth0,net0和net1。 eth0连接kubernetes集群网络以连接kubernetes服务器/服务(例如kubernetes api-server,kubelet等)。 net0和net1是其他网络附件,并通过使用其他CNI插件(例如vlan / vxlan / ptp)连接到其他网络。 MULTUS 工作原理Kubernetes当前没有提供为POD添加额外的接口选项的规定,或支持多个CNI插件同时工作的规定,但是它确实提供了一种由api服务器扩展受支持的API的机制。使用“自定义资源定义”可以做到这一点。 MULTUS依赖于“自定义资源定义”来存储其他接口和CNI插件所需的信息。 我们首先需要确保将MULTUS二进制文件放置在/opt/cni/bin位置的所有节点上,并在/etc/cni/net.d位置创建一个新的配置文件。与MULTUS使用的kubeconfig文件一起使用。 在/etc/cni/net.d中创建的新配置文件基于集群中已经存在的默认网络配置。 在此之后,CRD用于定义新的种类名称“ NetworkAttachmentDefinition”,以及服务帐户和MULTUS的集群角色以及相应的绑定。这个新的集群角色将提供对随CRD添加的新API组以及默认API组中Pod资源的访问权限。 然后创建类型为“ NetworkAttachmentDefinition”的客户资源实例,该实例稍后将在创建具有多个接口的Pod时使用。 部署示例在本文中,我们将多次提及两件事: “默认网络”-这是您的Pod到Pod网络。这就是集群中Pod之间相互通信的方式,以及它们之间的连通性。一般而言,这被称为名为eth0的接口。此接口始终连接到您的Pod,以便它们之间可以相互连接。除此之外,我们还将添加接口。“ CRD”-自定义资源定义。自定义资源是扩展Kubernetes API的一种方式。我们在这里使用这些存储Multus可以读取的一些信息。首先,我们使用它们来存储附加到您的Pod的每个其他接口的配置。目前支持Kubernetes 1.16+版本。 安装我们建议的用于部署Multus的快速入门方法是使用Daemonset(在群集中的每个节点上运行Pod的方法)进行部署,该Pod会安装Multus二进制文件并配置Multus以供使用。 首先,克隆此GitHub存储库。 git clone https://github.com/intel/multus-cni.git && cd multus-cni我们将在此存储库中使用带有kubectl的YAML文件。 $ cat ./images/multus-daemonset.yml | kubectl apply -f -Multus daemonset 完成了那些工作?启动Multus守护程序集,这会在每个节点上运行一个pod,从而在/opt/cni/bin中的每个节点上放置一个Multus二进制文件按照字母顺序读取/etc/cni/net.d中的第一个配置文件,并为Multus创建一个新的配置文件,即/etc/cni/net.d/00-multus.conf,此配置是自动生成并基于默认网络配置(假定是按字母顺序排列的第一个配置)在每个节点上创建一个/etc/cni/net.d/multus.d目录,其中包含用于Multus访问Kubernetes API的身份验证信息。创建其他接口我们要做的第一件事是为我们附加到Pod的每个其他接口创建配置。我们将通过创建自定义资源来做到这一点。快速入门安装的一部分会创建一个“ CRD”(自定义资源定义,它是我们保留这些自定义资源的位置),我们将在其中存储每个接口的配置。 CNI 配置我们将添加的每个配置都是CNI配置。如果您不熟悉它们,让我们快速分解它们。这是一个示例CNI配置: { "cniVersion": "0.3.0", "type": "loopback", "additional": "information"}CNI配置是JSON,我们这里有一个结构,其中包含一些我们感兴趣的东西: cniVersion:告诉每个CNI插件正在使用哪个版本,如果使用的版本太晚(或太早),则可以提供插件信息。type:告诉CNI在磁盘上调用哪个二进制文件。每个CNI插件都是一个二进制文件。通常,这些二进制文件存储在每个节点上的/opt/cni/bin中,并且CNI执行此二进制文件。在这种情况下,我们指定了loopback二进制文件(它将创建一个loopback类型的网络接口)。如果这是您首次安装Multus,则可能需要验证"type"字段中的插件是否确实在/opt/cni/bin目录中。additional:此字段以此处为例,每个CNI插件都可以在JSON中指定所需的任何配置参数。这些特定于您在"type"字段中调用的二进制文件。当CNI配置更改时,您不需要重新加载或刷新Kubelets。每次创建和删除Pod时都会读取这些内容。因此,如果您更改配置,它将在下一次创建Pod时应用。如果现有Pod需要新配置,则可能需要重新启动。 将配置存储为自定义资源因此,我们要创建一个附加接口。让我们创建一个macvlan接口供Pod使用。我们将创建一个自定义资源,该资源定义接口的CNI配置。 请注意,在以下命令中有一种:NetworkAttachmentDefinition。这是我们配置的名字-它是Kubernetes的自定义扩展,定义了我们如何将网络连接到Pod。 其次,注意配置字段。您将看到这是一个CNI配置,就像我们前面解释的那样。 最后但非常重要的一点是,在元数据下注意name字段-在这里我们为该配置指定名称,这是我们告诉pod使用此配置的方式。这里的名称是macvlan-conf-我们正在为macvlan创建配置。 ...

June 5, 2020 · 2 min · jiezi

细数k8s支持的4种类型的container

截止目前k8s1.18,k8s已经支持标准容器,sidecar容器,init 容器,ephemeral 容器 4种类型的containers。本文我们详细介绍一下这4种容器的特性已经使用场景。 Ephemeral 容器临时容器与其他容器的不同之处在于,它们缺少对资源或执行的保证,并且永远不会自动重启,因此不适用于构建应用程序。临时容器使用与常规容器相同的ContainerSpec段进行描述,但许多字段是不相容且不允许的。 临时容器没有端口配置,因此像ports,livenessProbe,readinessProbe这样的字段是不允许的。Pod 资源分配是不可变的,因此resources配置是不允许的。有关允许字段的完整列表,请参见临时容器参考文档。临时容器是使用 API 中的一种特殊的ephemeralcontainers处理器进行创建的,而不是直接添加到pod.spec段,因此无法使用kubectl edit来添加一个临时容器。 与常规容器一样,将临时容器添加到 Pod 后,将不能更改或删除临时容器。 为什么我们需要Ephemeral 容器? 我们知道容器的优点是它们通过使用不变方法提供所有必需的依赖项来运行隔离的进程。通过仅将所需的依赖项添加到镜像中,容器可以降低攻击面并提供更快的启动和部署。使用“distroless”方法构建容器镜像(基于scratch),通过仅包含已编译的应用程序二进制文件,将容器镜像提升到了一个新的水平。与普通的容器镜像不同,它们不基于任何种类的Linux发行版,因此不包含任何其他可通过kubectl exec执行以进行故障排除的二进制文件和工具。这就决定了该容器有助于提供安全可靠的运行时环境,但也很难在问题发生时进行调试。 在这种情况下,临时容器发挥作用。它们实现了调试容器附加到主进程的功能,然后你可以用于调试任何类型的问题。调试容器可以基于任何镜像,因此可以根据您的需求进行定制。您可以构建自己的调试镜像,其中包含特殊的调试二进制文件或仅包含curl,OpenSSL和MongoDB客户端之类的工具。但是,您也可以选择Linux发行版(如Ubuntu)或仅运行Busybox镜像,这两个镜像都已经包含了许多有用的工具。 如何使用临时容器? 临时容器是alpha功能,因此默认情况下处于禁用状态。您将需要激活以下功能门才能使用它们: 临时容器PodShareProcessNamespace(v1.16中的beta版,因此默认情况下已启用)本节中的示例演示了临时容器如何出现在 API 中。 通常,您可以使用kubectl插件进行故障排查,从而自动化执行这些步骤。 临时容器是使用 Pod 的ephemeralcontainers子资源创建的,可以使用kubectl --raw命令进行显示。首先描述临时容器被添加为一个EphemeralContainers列表: { "apiVersion": "v1", "kind": "EphemeralContainers", "metadata": { "name": "example-pod" }, "ephemeralContainers": [{ "command": [ "sh" ], "image": "busybox", "imagePullPolicy": "IfNotPresent", "name": "debugger", "stdin": true, "tty": true, "terminationMessagePolicy": "File" }]}使用如下命令更新已运行的临时容器example-pod: kubectl replace --raw /api/v1/namespaces/default/pods/example-pod/ephemeralcontainers -f ec.json这将返回临时容器的新列表: { "kind":"EphemeralContainers", "apiVersion":"v1", "metadata":{ "name":"example-pod", "namespace":"default", "selfLink":"/api/v1/namespaces/default/pods/example-pod/ephemeralcontainers", "uid":"a14a6d9b-62f2-4119-9d8e-e2ed6bc3a47c", "resourceVersion":"15886", "creationTimestamp":"2019-08-29T06:41:42Z" }, "ephemeralContainers":[ { "name":"debugger", "image":"busybox", "command":[ "sh" ], "resources":{ }, "terminationMessagePolicy":"File", "imagePullPolicy":"IfNotPresent", "stdin":true, "tty":true } ]}可以使用以下命令查看新创建的临时容器的状态: ...

June 2, 2020 · 2 min · jiezi

k8s部署单实例VictoriaMetrics完整教程

上一篇文章,我们讲述了如何利用VictoriaMetrics作为Prometheus的长期存储,来实现大规模k8s集群的监控。本文主要讲述部署单实例VictoriaMetric到k8s集群中。 部署VictoriaMetrics本文中,我们只会部署一个单实例的VictoriaMetrics。我们会在以后的文章中部署集群版本。 完整的yaml如下: --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: victoriametrics namespace: kube-system annotations: volume.beta.kubernetes.io/aws-block-storage-additional-resource-tags: "project=victoriametrics" spec: accessModes: - ReadWriteOnce resources: requests: storage: 100Gi--- apiVersion: apps/v1 kind: StatefulSet metadata: labels: app: victoriametrics name: victoriametrics namespace: kube-system spec: serviceName: pvictoriametrics selector: matchLabels: app: victoriametrics replicas: 1 template: metadata: labels: app: victoriametrics spec: containers: - args: - --storageDataPath=/storage - --httpListenAddr=:8428 - --retentionPeriod=1 image: victoriametrics/victoria-metrics imagePullPolicy: IfNotPresent name: victoriametrics ports: - containerPort: 8428 protocol: TCP readinessProbe: httpGet: path: /health port: 8428 initialDelaySeconds: 30 timeoutSeconds: 30 livenessProbe: httpGet: path: /health port: 8428 initialDelaySeconds: 120 timeoutSeconds: 30 resources: limits: cpu: 2000m memory: 2000Mi requests: cpu: 2000m memory: 2000Mi volumeMounts: - mountPath: /storage name: storage-volume restartPolicy: Always priorityClassName: system-cluster-critical volumes: - name: storage-volume persistentVolumeClaim: claimName: victoriametrics--- apiVersion: v1 kind: Service metadata: labels: app: victoriametrics name: victoriametrics namespace: kube-system spec: ports: - name: http port: 8428 protocol: TCP targetPort: 8428 selector: app: victoriametrics type: ClusterIPPS: ...

June 2, 2020 · 13 min · jiezi

Kubernetes集群node节点规格的选择

创建Kubernetes集群时,首先出现的问题之一是:“我应该使用哪种类型的node节点,其中有多少个? 如果要构建本地群集,应该订购一些上一代的服务器,还是使用数据中心中的十几台旧计算机? 或者,如果您使用的是诸如Google Kubernetes Engine(GKE)之类的托管Kubernetes服务,是否应该使用八个n1-standard-1或两个n1-standard-4实例来实现所需的计算能力? 集群容量通常,Kubernetes集群可以看作将一组单个节点抽象为一个大的“超级节点”。 该超级节点的总计算能力(就CPU和内存而言)是所有组成节点的能力之和。 有多种方法可以计算出集群的所需目标容量。 例如,假设您需要一个总容量为8个CPU内核和32 GB RAM的集群。 例如,由于要在集群上运行的一组应用程序需要此数量的资源。以下是设计集群的两种可能方法: 这两个选项都将导致群集具有相同的容量-但左边的选项使用4个较小的节点,而右边的选项使用2个较大的节点。 哪个更好? 为了解决这个问题,让我们看一下“很少有大节点”和“很多小节点”这两个相反方向的利弊。 请注意,本文中的“节点”始终指的是工作程序节点。主节点的数量和大小的选择是一个完全不同的主题。数量少的大资源节点在这个方向上,最极端的情况是拥有一个提供全部所需集群容量的单个工作节点。 在上面的示例中,这将是具有16个CPU内核和16 GB RAM的单个工作节点。 让我们看看这种方法可能具有的优势。 1. 较少的管理负担简而言之,与必须管理大量计算机相比,管理少量计算机较省力。 更新和补丁可以更快地应用,机器可以更轻松地保持同步。 此外,几台机器上的预期故障的绝对数量比多台机器要少。 但是,请注意,这主要适用于裸机服务器,不适用于云实例。 如果您使用云实例(作为托管Kubernetes服务的一部分或您在云基础架构上自己的Kubernetes安装的一部分),则将对基础机器的管理外包给云提供商。 因此,在云中管理10个节点并没有比在云中管理单个节点更多的工作。 2. 更少的成本虽然功能更强大的机器比低端机器更昂贵,但价格上涨并不一定是线性的。 换句话说,一台具有10个CPU内核和10 GB RAM的计算机可能比10台具有1个CPU内核和1 GB RAM的计算机便宜。 但是,请注意,如果您使用云实例,则这可能不适用。 在主要云提供商Amazon Web Services,Google Cloud Platform和Microsoft Azure的当前定价方案中,实例价格随容量线性增加。 例如,在Google Cloud Platform上,64个n1-standard-1实例的成本与单个n1-standard-64实例的成本完全相同—并且这两个选项都为您提供64个CPU内核和240 GB内存。 因此,在云中,通常无法使用大型计算机节省任何资金。 3. 允许运行占用资源多的应用拥有大型节点可能只是您要在集群中运行的应用程序类型的要求。 例如,如果您有一个需要8 GB内存的机器学习应用程序,则无法在只有1 GB内存的节点的集群上运行它。 但是您可以在具有10 GB内存节点的集群上运行它。 1. 每个节点运行太多的应用在更少的节点上运行相同的工作负载自然意味着在每个节点上运行更多的Pod。 这可能成为一个问题。 原因是每个Pod都会在节点上运行的Kubernetes代理上引入一些开销-例如容器运行时(例如Docker),kubelet和cAdvisor。 例如,kubelet对节点上的每个容器执行常规的活动性和就绪性探针-更多的容器意味着kubelet在每次迭代中需要进行更多的工作。 cAdvisor收集节点上所有容器的资源使用情况统计信息,并且kubelet定期查询此信息并将其公开在其API上-再次,这意味着cAdvisor和kubelet在每次迭代中都需要做更多的工作。 如果Pod的数量变大,这些事情可能会开始减慢系统速度,甚至使系统不可靠。、 有报告称节点未准备就绪,因为常规的kubelet运行状况检查花费了太长时间,无法遍历节点上的所有容器。 由于这些原因,Kubernetes建议每个节点最多110个Pod。 直到此数目,Kubernetes已经过测试,可以在常见节点类型上可靠地工作。 ...

June 2, 2020 · 1 min · jiezi

谈谈stop容器

docker stop对于docker来说,一般来说通过docker stop命令来实现停止容器,而不是docker kill。 具体命令如下: docker stop [OPTIONS] CONTAINER [CONTAINER...]容器内的主进程(PID为1的进程)将收到SIGTERM,并在宽限期之后收到SIGKILL。在容器中的应用程序,可以选择忽略和不处理SIGTERM信号,不过一旦达到超时时间,程序就会被系统强行kill掉,因为SIGKILL信号是直接发往系统内核的,应用程序没有机会去处理它。 至于这个宽限期默认是10s,当然可以通过参数来制定具体时间。 docker stop --helpUsage: docker stop [OPTIONS] CONTAINER [CONTAINER...]Stop one or more running containersOptions: --help Print usage -t, --time int Seconds to wait for stop before killing it (default 10)而对于k8s来说,pod的宽限期默认是30s。通过terminationGracePeriodSeconds参数设置。 为什么需要优雅stop docker ?你的程序需要一些退出工作,比如保存checkpoint,回收一些资源对象等。如果你的服务是一个http server,那么你需要完成已经处理的请求。如果是长链接,你还需要主动关闭keepalive。 如果你是在k8s中运行容器,那么k8s整个机制是一种基于watch的并行机制,我们不能保证操作的串行执行。比如在删除一个Pod的时候,需要更改iptables规则,LB的upstream 摘除等。 你的应用程序为什么接收不到SIGTERM停机信号?你的业务进程不是1号进程Dockerfile中支持两种格式定义入口点:shell格式和exec 格式。 exec格式如下: ENTRYPOINT ["/app/bin/your-app", "arg1", "arg2"]该格式能保证你的主进程接受到停机信号。 示例: 程序代码如下: package mainimport ( "fmt" "os" "os/signal" "syscall" "time")func main() { c := make(chan os.Signal) // 监听信号 signal.Notify(c, syscall.SIGTERM) go func() { for s := range c { switch s { case syscall.SIGTERM: fmt.Println("退出:", s) ExitFunc() default: fmt.Println("其他信号:", s) } } }() fmt.Println("启动了程序") sum := 0 for { sum++ fmt.Println("休眠了:", sum, "秒") time.Sleep(1 * time.Second) }}func ExitFunc() { fmt.Println("开始退出...") fmt.Println("执行清理...") fmt.Println("结束退出...") os.Exit(0)}Dockerfiler如下,我们采用多阶段构建: ...

May 30, 2020 · 4 min · jiezi

小试-cdk8s

cdk8s是一个由aws开源的软件开发框架,用于使用熟悉的编程语言和丰富的面向对象的API定义Kubernetes应用程序和可重用的抽象。 cdk8s生成纯Kubernetes YAML--您可以使用cdk8s为在任何地方运行的任何Kubernetes集群定义应用程序。 特性与Kubernetes一起使用:您可以使用cdk8s为在任何地方运行的任何Kubernetes集群(包括任何云或本地)定义应用程序。 cdk8s在您的开发环境中本地运行,并生成可应用于任何集群的标准Kubernetes YAML。多语言支持:目前将支持TypeScript,JavaScript,Python,Java和.NET,将来还会有更多支持。它可以与Kubernetes的任何上游版本一起使用。支持核心Kubernetes对象和自定义资源:您可以从任何Kubernetes API版本和自定义资源定义导入对象以与cdk8s一起使用。这使得使用cdk8s轻松编写整个Kubernetes应用程序变得容易,并在应用程序更改时使它们保持最新。与GitOps工作流程完美配合,使您在修改配置时以及在API版本之间轻松查看更改。只需使用cdk8来合成新的YAML配置文件并将它们提交到git repo。社区驱动。设计原理cdk8s应用程序是使用一种受支持的编程语言编写的程序。它们被构造为构造树。 树的根是一个App构造。在应用程序中,用户可以定义任意数量的图表(扩展了Chart类的类)。每个图表都被合成到一个单独的Kubernetes清单文件中。图表依次由任意数量的构造组成,最终由资源组成,这些资源代表任何Kubernetes资源,例如Pod,Service,Deployment,ReplicaSet等。 构造是cdk8的基本构建块。它们是通过普通的面向对象的类来构成和创建更高级别的抽象的工具。 如果您来自Kubernetes世界,则可以将构造视为以编程方式定义的Helm Charts。关于“以编程方式定义”构造的好处是,我们可以使用它们来利用面向对象编程的全部功能。例如: 您可以使用强类型数据类型来表达抽象的API您可以表达与方法和属性的丰富交互您可以通过接口和基类创建多态编程模型通过常规软件包管理器共享它们使用我们熟悉的测试工具和技术对其进行测试版本管理cdk8s应用程序仅定义Kubernetes应用程序,实际上并未将其应用于集群。执行某个应用程序时,它会将应用程序中定义的所有图表综合到dist目录中,然后可以使用kubectl apply -f dist/chart.k8s.yaml或GitOps工具(如Flux)将这些图表应用于任何Kubernetes集群。 示例让我们来看一个简单的"Hello,World!" TypeScript中的示例。 先决条件 Node.js >= 10.x你最喜欢的 editor/IDEyarn (可选)个人比较喜欢vscode,vscode 对cdk8s支持非常好。 安装CLI cdk8s有一个CLI,其中包含一些有用的命令。让我们从全局安装cdk8s CLI开始: $ npm install -g cdk8s-cli安装成功有类似输出: usr/local/bin/cdk8s -> /usr/local/lib/node_modules/cdk8s-cli/bin/cdk8s+ cdk8s-cli@0.23.0创建工程 现在,我们将使用cdk8s init命令创建一个新的TypeScript cdk8s应用程序: $ mkdir hello$ cd hello$ cdk8s init typescript-appcreating a new project from template: typescript-app...这将执行以下操作: 创建一个新的项目目录安装cdk8s作为依赖项导入所有Kubernetes API对象将TypeScript编译为JavaScript最终我们可以看到如下输出: ======================================================================================================== Your cdk8s typescript project is ready! cat help Print this message Compile: npm run compile Compile typescript code to javascript (or "yarn watch") npm run watch Watch for changes and compile typescript in the background npm run build Compile + synth Synthesize: npm run synth Synthesize k8s manifests from charts to dist/ (ready for 'kubectl apply -f') Deploy: kubectl apply -f dist/*.k8s.yaml Upgrades: npm run import Import/update k8s apis (you should check-in this directory) npm run upgrade Upgrade cdk8s modules to latest version npm run upgrade:next Upgrade cdk8s modules to latest "@next" version (last commit)========================================================================================================watch ...

May 29, 2020 · 2 min · jiezi

您可以在Kubernetes中使用API网关公开微服务吗

在Kubernetes中,Ingress是一个组件,可将流量从群集外部路由到群集中的服务和Pod。 简而言之,Ingress充当反向代理或负载平衡器:所有外部流量都路由到Ingress,然后路由到其他组件。 尽管最受欢迎的Ingress是ingress-nginx项目,但是在选择和使用Ingress时还有其他几种选择。 您可以从以下Ingress控制器中选择: 处理诸如Contour或Treafik Ingress之类的HTTP流量支持UDP和TCP流量,例如Citrix Ingress支持Websocket,例如HAProxy Ingress还有其他混合式Ingress控制器可以与现有的云提供商集成,例如Zalando的Skipper Ingress。 当谈到Kubernetes中的API网关时,有一些流行的选择可供选择。 选项1 — API网关之王:Kong如果要构建API,则可能会对Kong Ingress提供的功能感兴趣。 Kong是建立在Nginx之上的API网关。 Kong专注于API管理,并提供身份验证,速率限制,重试,断路器等功能。 Kong的有趣之处在于它以Kubernetes Ingress的形式打包。 因此,它可以在您的群集中用作用户和后端服务之间的网关。 您可以使用标准Ingress对象将API暴露给外部流量: apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata: name: my-ingressspec: rules: - host: example.com http: paths: - path: / backend: serviceName: api-service servicePort: 80但是 在安装过程中,Kong的控制器会注册自定义资源定义(CRD)。 这些自定义扩展之一与Kong的插件有关。 如果您希望通过IP地址限制对Ingress的请求,则可以使用以下方法创建限制的定义: apiVersion: configuration.konghq.com/v1kind: KongPluginmetadata: name: rl-by-ipconfig: hour: 100 limit_by: ip second: 10plugin: rate-limiting您可以在Ingress中使用以下注释来引用限制: apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata: name: my-ingress annotations: plugins.konghq.com: rl-by-ipspec: rules: - host: example.com http: paths: - path: / backend: serviceName: api-service servicePort: 80您可以在官方文档中浏览有关Kong的自定义资源定义(CRD)。 ...

May 26, 2020 · 2 min · jiezi

Open-Policy-Agent简化了微服务授权

随着微服务的发展,经常遇到实施身份验证和授权(A&A)的问题。我们需要一个强大且集中管理的身份验证和授权策略。但是,应用程序的分布式性质使其难以实现。在本文中,我将探讨Open Policy Agent如何帮助简化授权问题。 让我们快速查看“身份验证和授权”的定义。认证是指识别用户(“who”)。而授权是指确定经过身份验证的用户具有的访问级别(“what”)。 我这篇文章的重点是授权部分。为了简单起见,我创建了一个带有一组微服务的示例应用程序。有一个基本的用户界面,我们可以在其中执行各种操作并查看结果。该应用程序的唯一目的是显示Open Policy Agent如何处理各种授权方案。在后续文章中,我们将扩展该应用程序的范围,以涵盖日益复杂的用例和策略管理。 示例应用首先,关于应用程序的一些上下文。我以销售团队通常使用的CPQ应用程序为客户配置报价为例。 有以下角色: 销售–具有“销售”角色的用户可以为其客户创建新报价并更新报价。但是,具有“销售”角色的用户不能删除商品。销售支持–支持人员,他们可以查看所有报价,但不能编辑任何报价。、销售管理员–行政人员可以查看所有报价,但不能编辑/创建任何报价。但是,如果需要确保清理,他们可以删除要约。由于我们专注于授权部分,因此我假设用户已经过身份验证,并且具有有效的JSON Web令牌(JWT)。每个API请求都在请求标头中包含此JWT。 在此处从github下载示例应用程序。按照自述文件中的安装说明进行操作,您应该可以使用URL http://<MINIKUBE URL>/访问UI。 授权实战基于我们在上面看到的角色,期望销售团队能够 创建新报价列出报价更新现有报价而销售支持团队只能列出报价,而不能编辑/创建报价。 Sales Admin团队只能列出报价并将其删除。 UI显示了多个按钮,每个按钮代表用户的操作。选择您要使用的角色,然后尝试创建,编辑或删除商品。 UI将提供有关操作是否成功的反馈。 那么,这里发生了什么?让我们快速了解一下当前的设置。 该应用程序具有两个微服务优惠和客户。 NGINX反向代理将这些API公开给外界。 NGINX截获每个API请求并请求授权服务以验证是否允许用户执行请求的操作。我们使用NGINX的auth_request指令来拦截传入的API调用。每个API调用都有一个Authorization标头,其中包含JWT。包括角色在内的整个用户信息都包含在JWT中。 授权服务有两个容器: 授权–一种定制服务(Authorization),用于接收请求并为Open Policy Agent创建格式化的输入请求。开放策略代理(OPA)–作为辅助工具运行,并公开http端点以与授权容器进行通信。基本上,NGINX将/authorize请求发送到Authorization容器以授权API调用。然后,授权服务咨询开放策略代理是否授权请求(是/否)。然后,它向NGINX返回成功(200 OK)或错误(403 Forbidden)响应。因此,NGINX允许API调用或向客户端返回403 Forbidden响应。 Open Policy Agent 是什么?Open Policy Agent(OPA,发音为“ oh-pa”)是一种开放源代码的通用策略引擎,它统一了整个堆栈中的策略执行。 OPA提供了一种高级的声明性语言,可让您将策略指定为代码和简单的API,以减轻软件决策的负担。您可以使用OPA在微服务,Kubernetes,CI / CD管道,API网关等中实施策略。 基本上,OPA将决策与执法脱钩。它接受结构化数据作为输入(JSON),并且可以返回决策(对/错)或任意结构化数据作为输出。 OPA使用rego作为策略语言。您可以在https://www.openpolicyagent.org/docs/latest/上了解有关rego和开放策略代理的更多信息。 授权服务详解让我们详细查看授权服务,以了解其工作原理。 我们在服务器模式下运行Open Policy Agent,并利用其REST API更新策略并获取策略决策。 Open Policy Agent公开REST API来创建或更新策略。PUT /v1/policies/<id>Content-Type: text/plain对于我们的示例,使用带有以下请求的终结点(在GitHub README中也提到了)来更新OPA中的策略。 curl -X PUT --data-binary @policies/httpapi.authz.rego http://<MINIKUBE URL>/authorize/v1/policies/httpapi/authz要根据此政策做出决定,还有另一个APIPOST /v1/data/<path>Content-Type: application/json这里的<path>是由软件package标识的策略的路径,例如package httpapi.authz。对于我们的示例,要删除商品ID“ 1000”,授权服务将使用以下请求正文调用端点http://localhost:8181/data/httpapi/authz: ...

May 26, 2020 · 1 min · jiezi

为什么-K8s-集群达万级规模阿里购物体验还能如丝顺滑

阿里妹导读:本文主要介绍阿里巴巴和蚂蚁金服在大规模生产环境中落地 Kubernetes 的过程中,在集群规模上遇到的典型问题以及对应的解决方案,内容包含对 etcd、kube-apiserver、kube-controller 的若干性能及稳定性增强,这些关键的增强是阿里巴巴和蚂蚁金服内部上万节点的 Kubernetes 集群能够平稳支撑 2019 年天猫 618 大促的关键所在。文内藏福利,向下滑滑滑,免费课程立刻领取~背景从阿里巴巴最早期的 AI 系统(2013)开始,集群管理系统经历了多轮的架构演进,到 2018 年全面的应用 Kubernetes ,这期间的故事是非常精彩的。这里忽略系统演进的过程,不去讨论为什么 Kubernetes 能够在社区和公司内部全面的胜出,而是将焦点关注到应用 Kubernetes 中会遇到什么样的问题,以及我们做了哪些关键的优化。 在阿里巴巴和蚂蚁金服的生产环境中,容器化的应用超过了 10k 个,全网的容器在百万的级别,运行在十几万台宿主机上。支撑阿里巴巴核心电商业务的集群有十几个,最大的集群有几万的节点。在落地 Kubernetes 的过程中,在规模上面临了很大的挑战,比如如何将 Kubernetes 应用到超大规模的生产级别。 罗马不是一天就建成的,为了了解 Kubernetes 的性能瓶颈,我们结合阿里和蚂蚁的生产集群现状,估算了在 10k 个节点的集群中,预计会达到的规模: 20w pods100w objects 我们基于 Kubemark 搭建了大规模集群模拟的平台,通过一个容器启动多个(50个)Kubemark 进程的方式,使用了 200 个 4c 的容器模拟了 10k 节点的 kubelet。在模拟集群中运行常见的负载时,我们发现一些基本的操作比如 Pod 调度延迟非常高,达到了惊人的 10s 这一级别,并且集群处在非常不稳定的状态。 当 Kubernetes 集群规模达到 10k 节点时,系统的各个组件均出现相应的性能问题,比如: etcd 中出现了大量的读写延迟,并且产生了拒绝服务的情形,同时因其空间的限制也无法承载 Kubernetes 存储大量的对象;API Server 查询 pods/nodes 延迟非常的高,并发查询请求可能地址后端 etcd oom;Controller 不能及时从 API Server 感知到在最新的变化,处理的延时较高;当发生异常重启时,服务的恢复时间需要几分钟;Scheduler 延迟高、吞吐低,无法适应阿里业务日常运维的需求,更无法支持大促态的极端场景。etcd improvements为了解决这些问题,阿里云容器平台在各方面都做了很大的努力,改进 Kubernetes 在大规模场景下的性能。 ...

October 17, 2019 · 5 min · jiezi

从零开始入门-K8s-可观测性你的应用健康吗

作者 | 莫源 阿里巴巴技术专家 一、需求来源 首先来看一下,整个需求的来源:当把应用迁移到 Kubernetes 之后,要如何去保障应用的健康与稳定呢?其实很简单,可以从两个方面来进行增强: 首先是提高应用的可观测性; 第二是提高应用的可恢复能力。 从可观测性上来讲,可以在三个方面来去做增强: 首先是应用的健康状态上面,可以实时地进行观测; 第二个是可以获取应用的资源使用情况; 第三个是可以拿到应用的实时日志,进行问题的诊断与分析。 当出现了问题之后,首先要做的事情是要降低影响的范围,进行问题的调试与诊断。最后当出现问题的时候,理想的状况是:可以通过和 K8s 集成的自愈机制进行完整的恢复。 二、Liveness 与 Readiness 本小节为大家介绍 Liveness probe 和 eadiness probe。 应用健康状态-初识 Liveness 与 Readiness Liveness probe 也叫就绪指针,用来判断一个 pod 是否处在就绪状态。当一个 pod 处在就绪状态的时候,它才能够对外提供相应的服务,也就是说接入层的流量才能打到相应的 pod。当这个 pod 不处在就绪状态的时候,接入层会把相应的流量从这个 pod 上面进行摘除。 来看一下简单的一个例子: 如下图其实就是一个 Readiness 就绪的一个例子: 当这个 pod 指针判断一直处在失败状态的时候,其实接入层的流量不会打到现在这个 pod 上。 当这个 pod 的状态从 FAIL 的状态转换成 success 的状态时,它才能够真实地承载这个流量。 Liveness 指针也是类似的,它是存活指针,用来判断一个 pod 是否处在存活状态。当一个 pod 处在不存活状态的时候,会出现什么事情呢? ...

October 16, 2019 · 5 min · jiezi

从零开始入门-K8s-应用存储和持久化数据卷核心知识

作者 | 至天 阿里巴巴高级研发工程师 一、Volumes 介绍Pod Volumes首先来看一下 Pod Volumes 的使用场景: 场景一:如果 pod 中的某一个容器在运行时异常退出,被 kubelet 重新拉起之后,如何保证之前容器产生的重要数据没有丢失?场景二:如果同一个 pod 中的多个容器想要共享数据,应该如何去做?以上两个场景,其实都可以借助 Volumes 来很好地解决,接下来首先看一下 Pod Volumes 的常见类型: 本地存储,常用的有 emptydir/hostpath;网络存储:网络存储当前的实现方式有两种,一种是 in-tree,它的实现代码是放在 K8s 代码仓库中的,随着 K8s 对存储类型支持的增多,这种方式会给 K8s 本身的维护和发展带来很大的负担;而第二种实现方式是 out-of-tree,它的实现其实是给 K8s 本身解耦的,通过抽象接口将不同存储的 driver 实现从 K8s 代码仓库中剥离,因此 out-of-tree 是后面社区主推的一种实现网络存储插件的方式;Projected Volumes:它其实是将一些配置信息,如 secret/configmap 用卷的形式挂载在容器中,让容器中的程序可以通过 POSIX 接口来访问配置数据;PV 与 PVC 就是今天要重点介绍的内容。Persistent Volumes 接下来看一下 PV(Persistent Volumes)。既然已经有了 Pod Volumes,为什么又要引入 PV 呢?我们知道 pod 中声明的 volume 生命周期与 pod 是相同的,以下有几种常见的场景: 场景一:pod 重建销毁,如用 Deployment 管理的 pod,在做镜像升级的过程中,会产生新的 pod并且删除旧的 pod ,那新旧 pod 之间如何复用数据?场景二:宿主机宕机的时候,要把上面的 pod 迁移,这个时候 StatefulSet 管理的 pod,其实已经实现了带卷迁移的语义。这时通过 Pod Volumes 显然是做不到的;场景三:多个 pod 之间,如果想要共享数据,应该如何去声明呢?我们知道,同一个 pod 中多个容器想共享数据,可以借助 Pod Volumes 来解决;当多个 pod 想共享数据时,Pod Volumes 就很难去表达这种语义;场景四:如果要想对数据卷做一些功能扩展性,如:snapshot、resize 这些功能,又应该如何去做呢?以上场景中,通过 Pod Volumes 很难准确地表达它的复用/共享语义,对它的扩展也比较困难。因此 K8s 中又引入了 Persistent Volumes概念,它可以将存储和计算分离,通过不同的组件来管理存储资源和计算资源,然后解耦 pod 和 Volume 之间生命周期的关联。这样,当把 pod 删除之后,它使用的 PV 仍然存在,还可以被新建的 pod 复用。 ...

October 16, 2019 · 6 min · jiezi

从零开始入门-K8s-K8s-的应用编排与管理

作者 | 张振 阿里巴巴高级技术专家 一、资源元信息1. Kubernetes 资源对象我们知道,Kubernetes 的资源对象组成:主要包括了 Spec、Status 两部分。其中 Spec 部分用来描述期望的状态,Status 部分用来描述观测到的状态。 今天我们将为大家介绍 K8s 的另外一个部分,即元数据部分。该部分主要包括了用来识别资源的标签:Labels, 用来描述资源的注解;Annotations, 用来描述多个资源之间相互关系的 OwnerReference。这些元数据在 K8s 运行中有非常重要的作用。 2. labels第一个元数据,也是最重要的一个元数据——资源标签。资源标签是一种具有标识型的 Key:Value 元数据,如下图所示,展示了几个常见的标签。 前三个标签都打在了 Pod 对象上,分别标识了对应的应用环境、发布的成熟度和应用的版本。从应用标签的例子可以看到,标签的名字包括了一个域名的前缀,用来描述打标签的系统和工具, 最后一个标签打在 Node 对象上,还在域名前增加了版本的标识 beta 字符串。 标签主要用来筛选资源和组合资源,可以使用类似于 SQL 查询 select,来根据 Label 查询相关的资源。 3. Selector最常见的 Selector 就是相等型 Selector。现在举一个简单的例子: 假设系统中有四个 Pod,每个 Pod 都有标识系统层级和环境的标签,我们通过 Tie:front 这个标签,可以匹配左边栏的 Pod,相等型 Selector 还可以包括多个相等条件,多个相等条件之间是逻辑”与“的关系。 在刚才的例子中,通过 Tie=front,Env=dev 的 Selector,我们可以筛选出所有 Tie=front,而且 Env=dev 的 Pod,也就是下图中左上角的 Pod。另外一种 Selector 是集合型 Selector,在例子中,Selector 筛选所有环境是 test 或者 gray 的 Pod。 ...

September 20, 2019 · 4 min · jiezi

从零开始入门-K8s-详解-Pod-及容器设计模式

作者|张磊 阿里云容器平台高级技术专家,CNCF 官方大使 一、为什么需要 Pod容器的基本概念我们知道 Pod 是 Kubernetes 项目里面一个非常重要的概念,也是非常重要的一个原子调度单位,但是为什么我们会需要这样一个概念呢?在使用容器 Docker 的时候,也没有这个说法。其实,如果想要理解 Pod,首先要理解容器,所以来回顾一下容器的概念:容器的本质实际上是一个进程,是一个视图被隔离,资源受限的进程。容器里面 PID=1 的进程就是应用本身,这意味着管理虚拟机等于管理基础设施,因为我们是在管理机器,但管理容器却等于直接管理应用本身。这也是之前说过的不可变基础设施的一个最佳体现,这个时候,你的应用就等于你的基础设施,它一定是不可变的。在以上面的例子为前提的情况下,Kubernetes 又是什么呢?很多人都说 Kubernetes 是云时代的操作系统,这个非常有意思,因为如果以此类推,容器镜像就是这个操作系统的软件安装包,它们之间是这样的一个类比关系。 真实操作系统里的例子如果说 Kubernetes 就是操作系统的话,那么不妨看一下真实的操作系统的例子。例子里面有一个程序叫做 Helloworld,这个 Helloworld 程序实际上是由一组进程组成的,需要注意一下,这里说的进程实际上等同于 Linux 中的线程。因为 Linux 中的线程是轻量级进程,所以如果从 Linux 系统中去查看 Helloworld 中的 pstree,将会看到这个 Helloworld 实际上是由四个线程组成的,分别是 {api、main、log、compute}。也就是说,四个这样的线程共同协作,共享 Helloworld 程序的资源,组成了 Helloworld 程序的真实工作情况。这是操作系统里面进程组或者线程组中一个非常真实的例子,以上就是进程组的一个概念。 那么大家不妨思考一下,在真实的操作系统里面,一个程序往往是根据进程组来进行管理的。Kubernetes 把它类比为一个操作系统,比如说 Linux。针对于容器我们前面提到可以类比为进程,就是前面的 Linux 线程。那么 Pod 又是什么呢?实际上 Pod 就是我们刚刚提到的进程组,也就是 Linux 里的线程组。 进程组概念说到进程组,首先建议大家至少有个概念上的理解,然后我们再详细的解释一下。还是前面那个例子:Helloworld 程序由四个进程组成,这些进程之间会共享一些资源和文件。那么现在有一个问题:假如说现在把 Helloworld 程序用容器跑起来,你会怎么去做?当然,最自然的一个解法就是,我现在就启动一个 Docker 容器,里面运行四个进程。可是这样会有一个问题,这种情况下容器里面 PID=1 的进程该是谁? 比如说,它应该是我的 main 进程,那么问题来了,“谁”又负责去管理剩余的 3 个进程呢?这个核心问题在于,容器的设计本身是一种“单进程”模型,不是说容器里只能起一个进程,由于容器的应用等于进程,所以只能去管理 PID=1 的这个进程,其他再起来的进程其实是一个托管状态。 所以说服务应用进程本身就具有“进程管理”的能力。比如说 Helloworld 的程序有 system 的能力,或者直接把容器里 PID=1 的进程直接改成 systemd,否则这个应用,或者是容器是没有办法去管理很多个进程的。因为 PID=1 进程是应用本身,如果现在把这个 PID=1 的进程给 kill 了,或者它自己运行过程中死掉了,那么剩下三个进程的资源就没有人回收了,这个是非常严重的一个问题。反过来,如果真的把这个应用本身改成了 systemd,或者在容器里面运行了一个 systemd,将会导致另外一个问题:使得管理容器不再是管理应用本身了,而等于是管理 systemd,这里的问题就非常明显了。比如说我这个容器里面 run 的程序或者进程是 systemd,那么接下来,这个应用是不是退出了?是不是 fail 了?是不是出现异常失败了?实际上是没办法直接知道的,因为容器管理的是 systemd。这就是为什么在容器里面运行一个复杂程序往往比较困难的一个原因。这里再帮大家梳理一下:由于容器实际上是一个“单进程”模型,所以如果你在容器里启动多个进程,只有一个可以作为 PID=1 的进程,而这时候,如果这个 PID=1 的进程挂了,或者说失败退出了,那么其他三个进程就会自然而然的成为孤儿,没有人能够管理它们,没有人能够回收它们的资源,这是一个非常不好的情况。 ...

September 19, 2019 · 4 min · jiezi

K8S中手动扩容云盘数据卷

介绍:云盘数据卷扩容包括以下几个部分: 云盘物理空间扩容,需要在云盘控制台操作;文件系统扩容,需要挂载云盘到一个物理节点手动操作;PV、PVC Size更新,需要更新StorageClass、PVC;注意:扩容云盘前需要为云盘打快照,以预防升级失败导致数据丢失; 云盘目前无法做到在线扩容,需要重启应用才可以实现,可以通过两种方法实现云盘扩容。下面以集群中部署Zookeeper为例介绍两种扩容方式,Zookeeper集群如下: # kubectl get podNAME READY STATUS RESTARTS AGEzookeeper-default-zookeeper-0 1/1 Running 0 2m55szookeeper-default-zookeeper-1 1/1 Running 0 2m14szookeeper-default-zookeeper-2 1/1 Running 0 94s# kubectl get pvc| grep zoodatadir-zookeeper-default-zookeeper-0 Bound d-8vb5teafaoa80ia7affg 20Gi RWO alicloud-disk-efficiency 3m12sdatadir-zookeeper-default-zookeeper-1 Bound d-8vb60faf6epslbctnzka 20Gi RWO alicloud-disk-efficiency 2m31sdatadir-zookeeper-default-zookeeper-2 Bound d-8vbidmq57w4df6k84zem 20Gi RWO alicloud-disk-efficiency 111s# kubectl get pv| grep zood-8vb5teafaoa80ia7affg 20Gi RWO Delete Bound default/datadir-zookeeper-default-zookeeper-0 alicloud-disk-efficiency 3m17sd-8vb60faf6epslbctnzka 20Gi RWO Delete Bound default/datadir-zookeeper-default-zookeeper-1 alicloud-disk-efficiency 2m33sd-8vbidmq57w4df6k84zem 20Gi RWO Delete Bound default/datadir-zookeeper-default-zookeeper-2 alicloud-disk-efficiency 107s暂停应用方式:如果应用可以暂停服务,可以先停掉应用(删除),手动对每个依赖数据盘进行扩容,然后再启动应用。缺点是:应用会暂停一定时间; ...

September 19, 2019 · 3 min · jiezi

超实用K8s-开发者必须知道的-6-个开源工具

文章来源:云原生实验室,点击查看原文。 导读:Kubernetes 作为云原生时代的“操作系统”,熟悉和使用它是每名用户(User)的必备技能。如果你正在 Kubernetes 上工作,你需要正确的工具和技巧来确保 Kubernetes 集群的高可用以及工作负载的稳定运行。本篇文章将为你详细介绍 6 个实用的 Kubernetes 开源工具,千万不要错过。前言随着 Kubernetes 的发展和演变,人们可以从内部来驯服它的无节制行为。但有些人并不情愿干等 Kubernetes 变得易于使用,并且为已投入生产的 Kubernetes 中遇到的很多常见问题制定了自己的解决方案。 这里我们将介绍一些提高操作效率的技巧,同时列举几个比较有用的开源 Kubernetes 工具,这些工具以各种方式简化 Kubernetes,包括简化命令行交互,简化应用程序部署语法等。 kubectl 自动补全kubectl 这个命令行工具非常重要,与之相关的命令也很多,我们也记不住那么多的命令,而且也会经常写错,所以命令自动补全是很有必要的,kubectl 工具本身就支持自动补全,只需简单设置一下即可。 bash 用户大多数用户的 shell 使用的是 bash,Linux 系统可以通过下面的命令来设置: $ echo "source <(kubectl completion bash)" >> ~/.bashrc$ source ~/.bashrc如果发现不能自动补全,可以尝试安装 bash-completion 然后刷新即可! zsh 用户如果你使用的 shell 是 zsh,可以通过下面的命令来设置: $ echo "source <(kubectl completion zsh)" >> ~/.zshrc$ source ~/.zshrc自定义 kubectl get 输出kubectl get 相关资源,默认输出为 kubectl 内置,一般我们也可以使用 -o json 或者 -o yaml 查看其完整的资源信息。但是很多时候,我们需要关心的信息并不全面,因此我们需要自定义输出的列,那么可以使用 go-template 来进行实现。 go-template 是 golang 的一种模板,可以参考 template 的相关说明。 比如仅仅想要查看获取的 pods 中的各个 pod 的 uid,则可以使用以下命令: ...

September 9, 2019 · 2 min · jiezi

k8s与存储flexvolume解读

前言k8s 非常厉害的地方就在于可扩展性,而存储领域,支持flexvolume 和 csi 两种方式来进行扩展。今天主要讲下flexvolume。FlexVolume 是 Kubernetes v1.8+ 支持的一种存储插件扩展方式。类似于 CNI 插件,它需要外部插件将二进制文件放到预先配置的路径中(如 /usr/libexec/kubernetes/kubelet-plugins/volume/exec/),并需要在系统中安装好所有需要的依赖。可以想到,这是一种out-tree的扩展方式,不需要新增加一种存储插件,去更改k8s的源码。 FlexVolume 接口官方提供了一些接口,在我们实现自定义存储插件的时候,需要实现部分接口,之所以说部分,主要是看自己的需求。比如我在实现动态hostpath(主机路径包含podid)的时候,就只实现了init和mount和unmount三个接口而已。 FlexVolume 的接口包括 init:kubelet/kube-controller-manager 初始化存储插件时调用,插件需要返回是否需要要 attach 和 detach 操作attach:将存储卷挂载到 Node 上detach:将存储卷从 Node 上卸载waitforattach: 等待 attach 操作成功(超时时间为 10 分钟)isattached:检查存储卷是否已经挂载mountdevice:将设备挂载到指定目录中以便后续 bind mount 使用unmountdevice:将设备取消挂载mount:将存储卷挂载到指定目录中umount:将存储卷取消挂载Driver outputFlexvolume希望驱动程序以下列格式回复操作状态 { "status": "<Success/Failure/Not supported>", "message": "<Reason for success/failure>", "device": "<Path to the device attached. This field is valid only for attach & waitforattach call-outs>" "volumeName": "<Cluster wide unique name of the volume. Valid only for getvolumename call-out>" "attached": <True/False (Return true if volume is attached on the node. Valid only for isattached call-out)> "capabilities": <Only included as part of the Init response> { "attach": <True/False (Return true if the driver implements attach and detach)> }}与kubelet 的关系前面讲到自定义的存储插件是放到/usr/libexec/kubernetes/kubelet-plugins/volume/exec/下,具体目录是/usr/libexec/kubernetes/kubelet-plugins/volume/exec/<vendor~driver>/<driver>。在pod的spec中申明用到了你自定义的插件后,格式为 <vendor~driver>/<driver>,实际上是kubelet 按照接口规范去调用对应插件。所以需要注意以下几点: ...

September 7, 2019 · 1 min · jiezi

kubernetes集群安装2019最新

集群安装准备工作请参考https://segmentfault.com/a/11900000201191901.环境介绍一共三台 CentOS Linux release 7.6.1810 (Core) 192.168.1.100 master 192.168.1.101 node1 192.168.1.102 node2 2.Master、Node节点安装、配置Docker# 卸载原来的dockersudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine# 安装依赖sudo yum update -y && sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 #添加阿里云yum源(官网的源比较慢)sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 安装docker的指定版本查看版本$ yum list docker-ce --showduplicates | sort -r$ sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io例如:yum install docker-ce-18.09.5 docker-ce-cli-18.09.5 containerd.io -y# 查看docker版本docker --version# 开机启动systemctl enable --now docker修改docker cgroup驱动,与k8s一致,使用systemd ...

August 21, 2019 · 2 min · jiezi

云原生生态周报-Vol-15-K8s-安全审计报告发布

业界要闻1.CNCF 公布 Kubernetes 的安全审计报告 报告收集了社区对 Kubernetes、CoreDNS、Envoy、Prometheus 等项目的安全问题反馈,包含从一般弱点到关键漏洞。报告帮项目维护人员解决已识别的漏洞,并给出了一系列最佳实践。 2.技术监督委员会(TOC)投票决定将 rkt 项目归档 尽管 rkt 在 2014 年 12 月创建最初很受欢迎,并在 2017 年 3 月贡献给 CNCF,但其采纳程度已严重下降,很多用户已经从 rkt 转向了如 containerd、CRI-O 等其它项目。 上游重要进展 Kubernetes 项目1.支持 readonly 的接口指定不同的网卡; https://github.com/kubernetes/enhancements/issues/1208 2.在 Kubectl 中进行 pod 问题定位分析;https://github.com/kubernetes/enhancements/pull/1204/fileshttps://github.com/kubernetes/enhancements/blob/master/keps/sig-node/20190212-ephemeral-containers.md#alternatives 方式:在运行时对已有的 pod,新增一个 ephemeral container 挂载到这个 pod 的 spec 下面,然后 status 中也会有一个 EphemeralContainers 的 debug 容器信息: a. Debug Container Namingb. Container Namespace Targeting:shared process namespacec. Interactive Troubleshooting and Automatic Attaching: ...

August 20, 2019 · 2 min · jiezi

Kubernetes-弹性伸缩全场景解析-四-让核心组件充满弹性

前言在本系列的前三篇文章中,我们介绍了弹性伸缩的整体布局以及 HPA 的一些原理,HPA 的部分还遗留了一些内容需要进行详细解析。在准备这部分内容的期间,会穿插几篇弹性伸缩组件的最佳实践。今天我们要讲解的是cluster-proportional-autoscaler 。 cluster-proportional-autoscaler 是根据集群中节点的数目进行 Pod 副本数水平伸缩的组件。这个组件的产生主要是为了解决集群的核心组件负载弹性的问题。在一个 Kubernetes 集群中,除了 APIServer 等耳熟能详的 Control Pannel 组件,还有很多系统组件是部署在 worker 上的,例如 CoreDNS、Ingress Controller、Istio 等等。 这些核心组件大部分和我们的应用接入层息息相关,也就是说每当我们的系统处理了一条外部的请求,可能都会调用这些组件。由于这些组件的负载过大,很有可能造成应用的QPS达到瓶颈。那么一个集群该运行多少个核心组件副本呢? 很遗憾,这个问题是没有统一答案的,因为不同的类型的应用、不同的网络模型、不同的调度分布,都有可能会带来不同的挑战。在本篇文章中,我们不谈具体的指标和数据,只探讨解法。在本系列后面的文章中,会为大家深入解析。 大部分的情况下,核心组件的副本数目和集群的节点数目是成正比的,一个集群的节点数目越多,核心组件所需要的副本数就越多。今天我们以 CoreDNS 为例,通过 cluster-proportional-autoscaler,来实现一个动态的、基于节点数目的核心组件动态伸缩。 cluster-proportional-autoscaler 的使用cluster-proportional-autoscaler 和传统的 Kubernetes 组件设计有所不同,我们已经见惯了各种 Controller、CRD 或者 Operator,而 cluster-proportional-autoscaler 走了另外一条非常简单的路。使用 cluster-proportional-autoscaler 只需要部署一个 Yaml 并选择一个伸缩的监听对象以及伸缩策略即可。如果需要有多个组件进行伸缩,那就部署多个 Yaml,每个 Yaml 包含一个 cluster-proportional-autoscaler。一个使用 cluster-proportional-autoscaler 弹性伸缩 coredns 的模板如下。 apiVersion: apps/v1kind: Deploymentmetadata: name: dns-autoscaler namespace: kube-system labels: k8s-app: dns-autoscalerspec: selector: matchLabels: k8s-app: dns-autoscaler template: metadata: labels: k8s-app: dns-autoscaler spec: serviceAccountName: admin containers: - name: autoscaler image: registry.cn-hangzhou.aliyuncs.com/ringtail/cluster-proportional-autoscaler-amd64:v1.3.0 resources: requests: cpu: "200m" memory: "150Mi" command: - /cluster-proportional-autoscaler - --namespace=kube-system - --configmap=dns-autoscaler - --target=Deployment/coredns - --default-params={"linear":{"coresPerReplica":16,"nodesPerReplica":2,"min":1,"max":100,"preventSinglePointFailure":true}} - --logtostderr=true - --v=2cluster-proportional-autoscaler 的伸缩策略主要有两种:一种是线性模型,一种是梯度模型。 ...

August 7, 2019 · 1 min · jiezi

云原生生态周报-Vol10-数据库能否运行在-K8s-当中

业界要闻 IBM 以总价 340 亿美元完成里程碑意义的红帽收购:这是这家拥有 107 年历史的公司史上规模最大的一笔收购,该收购金额在整个科技行业的并购史上也能排到前三。在当天公布的声明中,IBM 与 Red Hat 联合表示,双方合作将重点推进“混合云”业务,即让公司客户自身服务器上的数据与云服务进行对接,这一方案兼顾了传统企业IT服务解决方案以及新兴的基于云服务的解决方案,是最现实可行的一种路径选择。 Garnter 发布 2018 年全球云计算市场数据:据 Gartner 统计,2018 年全球云计算市场向头部进一步集中, 3A (亚马逊 AWS、微软 Azure、阿里云)占据七成市场份额。亚马逊依旧领跑,但市场份额已经见顶回撤。微软和阿里云均有市场份额增长,其中阿里云保持 3A 军团中最快增长,市场份额增长近一倍。而在另外 Gartner 一份《数据库的未来就是云》报告中,3A 同样位列前三。阿里云的市场份额在 DBMS 供应商中排名第三,同比增长 116%。目前阿里云云原生产品家族已经纳入了数据库核心产品,阿里云 Kubernetes 服务 (ACK) 通过与阿里云旗舰数据库产品 PolarDB 深度结合,正在帮助用户同时实现应用层面的快速弹性和数据层面无限扩容。 上游重要进展 Kubernetes 项目Kubernetes 设计增强(KEP):(a)  如何开发 K8s 自定义调度器插件?上周,上游 Scheduler Framework 插件开发的第一个指导性文档发布, 其中列出了几种开发调度插件方式的利弊: 直接 Vendor 上游 Scheduler 代码库,然后基于其中的 Framework 库开发插件 (推荐)通过 Golang Plugin 机制: 这个方法对 Golang 版本依赖严重,跨版本无法使用;对启动和部署也带来很多挑战;通过 hashicorp/go-plugin 机制: 使用方式不友好,复杂;性能较前两种方案差(b) Sidecar KEP(Pod 中允许声明某些容器为 Sidecar,从而更精细化的管理这些容器的生命周期)详细解读: ...

July 16, 2019 · 2 min · jiezi

初探云原生应用管理一-Helm-与-App-Hub

系列介绍:初探云原生应用管理系列是介绍如何用云原生技术来构建、测试、部署、和管理应用的内容专辑。做这个系列的初衷是为了推广云原生应用管理的最佳实践,以及传播开源标准和知识。通过这个系列,希望帮助大家学到 Kubernetes、Helm、Gitops、Kustomize 等新知识。 这是大厂程序员小张普普通通的一个早晨,大家好像在讨论着什么: “什么?听说隔壁公司在用 K8s 发布应用了?” “据说在用 Helm !” 像往常,小张根本不关心这些无聊的讨论。他稳稳的坐在办公桌前,打开公司内部自研的、魔改 Gitlab  打造的项目管理系统,点击了好几个 Button 之后,开始一天辛勤的劳作。 但这一次不知道为何,小张的内心居然有点慌:“ Helm?啥是 Helm ?” ------ 分割线 ------ Helm:  K8s 应用部署与打包工具如果一个用户想要部署起来一个K8s 应用,最快捷的方法是什么呢? 我们知道,Kubernetes (简称 k8s ) 是一个能够部署和管理容器的平台。然而,在 k8s 里还没有抽象到“应用”这一层概念。一个应用往往由多个 k8s 资源 ( Deployment、Service、ConfigMap )组成。所以,我们需要一个工具在 k8s 之上来部署和管理一个应用所包含的资源( K8s API Resource ),这就是 Helm 所做的事情。 除此以外,Helm 定义了一套 Chart 格式来描述一个应用。怎么理解 Chart 呢?打个比方,一个安卓程序打包成 APK 格式,就可以安装到任意一台运行安卓系统的手机上。如果我们把 k8s 比做安卓系统,K8s 应用比做安卓程序,那么 Chart 就可以比做 APK。这也意味着,K8s 应用只要打包成 Chart ,就可以通过 Helm 部署到任意一个 k8s 集群上。 ...

July 9, 2019 · 3 min · jiezi

Knative-初体验Build-Hello-World

作者 | 阿里云智能事业群技术专家 冬岛  Build 模块提供了一套 Pipeline 机制。Pipeline 的每一个步骤都可以执行一个动作,这个动作可以是把源码编译成二进制、可以是编译镜像也可以是其他的任何事情。Knative Build 执行编译的时候并不需要我们提前准备编译环境,所有这些都是直接在 Pod 中执行的。当有任务需要执行的时候 Build 模块就自动创建 Pod 进行相应的处理。所以这一系列的动作都是 Kubernetes 原生的。 Knative Build 的几个关键特性一个完整的 Build 是由多个 Builder 构成的 Pipeline,每一个 Builder 可以执行一个或多个操作一个 Builder 在执行的时候就是一个 container,而且容器的镜像是声明 Builder 的时候用户自己指定的,所以可以在 container 里面执行任何指令基于 Kaniko 可以在 Builder 中编译镜像以及把镜像推送到镜像仓库等操作BuildTemplate 提供了可以重复使用的模板Build 过程可以从 git 仓库 clone 代码、向镜像仓库 push 镜像。所有这些动作使用到的鉴权信息都可以通过 serviceAccount 进行关联。直接使用 Kubernetes 原生的能力即可实现Build 示例既然是 Hello World 我们就从一个具体的例子谈起。 apiVersion: build.knative.dev/v1alpha1kind: Buildmetadata: name: example-build-namespec: serviceAccountName: build-auth-example source: git: url: https://github.com/example/build-example.git revision: master steps: - name: ubuntu-example image: ubuntu args: ["ubuntu-build-example", "SECRETS-example.md"] - image: gcr.io/example-builders/build-example args: ["echo", "hello-example", "build"] - name: dockerfile-pushexample image: gcr.io/example-builders/push-example args: ["push", "${IMAGE}"] volumeMounts: - name: docker-socket-example mountPath: /var/run/docker.sock volumes: - name: example-volume emptyDir: {}关键字段解释: ...

July 5, 2019 · 3 min · jiezi

为OKDOpenshift集群配置OpenLDAP认证

前言如同Linux操作系统安装完成后,管理员需为应用创建不同的用户,那么,K8S/OKD/Openshift集群同样也需如此,而在OKD/Openshift集群里,我们可集成OpenLDAP目录系统,方法如下所示。 OpenLDAP安装本文使用helm安装openldap,首先将chars下载下来以方便查看: git clone https://github.com/helm/charts可选。镜像可先推送到私有仓库(PS:测试发现latest镜像有问题): docker pull osixia/openldap:1.2.1docker tag docker.io/osixia/openldap:1.2.1 okd-lr.zyl.io:5001/osixia/openldap:1.2.1docker push okd-lr.zyl.io:5001/osixia/openldap:1.2.1镜像以root用户运行(gosudo切换),赋权: oc new-project auth-openshiftoc adm policy add-scc-to-user anyuid -z default对openldap char参数做定制: cd charts/stable/openldapcp values.yaml values_cs.yamlvi values_cs.yaml...env: # LDAP将创建dc=zyl,dc=io域,组织名称为Zyl Inc. LDAP_ORGANISATION: "Zyl Inc." LDAP_DOMAIN: "zyl.io"...# Ldap域管理员(cn=admin,dc=zyl,dc=io)及config管理员(cn=admin,cn=config)密码adminPassword: adminconfigPassword: config# 持久化存储,本例使用已创建好的glusterfs存储系统,其支持动态提供。persistence: enabled: true storageClass: "glusterfs-app" accessMode: ReadWriteOnce size: 8Gi执行helm命令安装: helm install --name openldap -f values_cs.yaml .Ldap启动后,创建了域dc=zyl,dc=io及hdb管理员账户cn=admin,dc=zyl,dc=io。如下所示,在此域下创建用户与组信息: % oc rsh deploy/openldap% cat > users.ldif <<EOFdn: ou=People,dc=zyl,dc=ioou: PeopleobjectClass: topobjectClass: organizationalUnitdn: ou=Group,dc=zyl,dc=ioou: GroupobjectClass: topobjectClass: organizationalUnitdn: uid=zyl,ou=People,dc=zyl,dc=iouid: zylcn: zylobjectClass: accountobjectClass: posixAccountobjectClass: topobjectClass: shadowAccountuserPassword: changemeloginShell: /bin/bashuidNumber: 5000gidNumber: 5000homeDirectory: /home/zyldn: uid=admin,ou=People,dc=zyl,dc=iouid: admincn: adminobjectClass: accountobjectClass: posixAccountobjectClass: topobjectClass: shadowAccountuserPassword: changemeloginShell: /bin/bashuidNumber: 5001gidNumber: 5001homeDirectory: /home/admindn: cn=zyl,ou=Group,dc=zyl,dc=iocn: zylobjectClass: topobjectClass: posixGroupgidNumber: 5000memberUid: zyldn: cn=admin,ou=Group,dc=zyl,dc=iocn: adminobjectClass: topobjectClass: posixGroupgidNumber: 5001memberUid: admindn: cn=openshift_user,ou=Group,dc=zyl,dc=iocn: openshift_userobjectClass: topobjectClass: posixGroupgidNumber: 6000memberUid: zyldn: cn=openshift_admin,ou=Group,dc=zyl,dc=iocn: openshift_adminobjectClass: topobjectClass: posixGroupgidNumber: 6001memberUid: adminEOF% ldapadd -x -w $LDAP_ADMIN_PASSWORD -D "cn=admin,dc=zyl,dc=io" -H ldapi:/// -f users.ldif% ldapsearch -x -D "cn=admin,dc=zyl,dc=io" -w $LDAP_ADMIN_PASSWORD \ -b dc=zyl,dc=io# 可使用config管理员检查ldap config配置% ldapsearch -x -D "cn=admin,cn=config" -w $LDAP_CONFIG_PASSWORD \ -b cn=config "olcDatabase=config"配置Master使用Ldap认证OKD初始安装时若未配置openshift_master_identity_providers,则OKD默认使用如下认证,此认证方式允许任何用户登录集群。 ...

June 28, 2019 · 2 min · jiezi

在K8S集群下为应用配置本地卷Local-Volume

本地卷描述如Hadoop、ES等系统,其DataNode需大量存储,且其本身提供了冗余功能,那么我们就没必要让其从存储系统中分配卷,而是像裸机部署一样让其使用本地节点上的存储,local volumes出现之前,我们可使用HostPath挂载卷到容器中,但此方案有很多局限性: The prior mechanism of accessing local storage through hostPath volumes had many challenges. hostPath volumes were difficult to use in production at scale: operators needed to care for local disk management, topology, and scheduling of individual pods when using hostPath volumes, and could not use many Kubernetes features (like StatefulSets). Existing Helm charts that used remote volumes could not be easily ported to use hostPath volumes. The Local Persistent Volumes feature aims to address hostPath volumes’ portability, disk accounting, and scheduling challenges.注意:本地卷仅适用于少量应用,如同HostPath一样Pod被绑定到特定的主机上,若主机异常,则Pod没法调度到其他节点,其适用场景: ...

June 28, 2019 · 3 min · jiezi

mysql-dockerentrypointsh分析

Docker Hub中有很多好用的Docker镜像,但镜像到底如何工作、能做什么、怎么做值得我们研究,如下所示为MySQL官方镜像的docker-entrypoint.sh脚本分析: #!/bin/bashset -eo pipefailshopt -s nullglob################################################################# 若启动命令时附加了参数,则在参数前添加mysqld,如$0 -f test,则经过此代码处理后,# $@参数变mysqld -f test。其中${1:0:1}从$1参数第0个位置取1字符,如$1为-f,则# 取'-'字符,若条件为真,通过set命令重置$@参数,添加mysqld前缀,即经过处理后$1变# 为mysqld。################################################################# if command starts with an option, prepend mysqldif [ "${1:0:1}" = '-' ]; then set -- mysqld "$@"fi# 解析参数,是否是获取帮助信息参数,并设置wantHelp值###################################################### skip setup if they want an option that stops mysqldwantHelp=for arg; do case "$arg" in -'?'|--help|--print-defaults|-V|--version) wantHelp=1 break ;; esacdone############################## 从文件中读取变量值############################## usage: file_env VAR [DEFAULT]# ie: file_env 'XYZ_DB_PASSWORD' 'example'# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)file_env() { local var="$1" local fileVar="${var}_FILE" local def="${2:-}" if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then echo >&2 "error: both $var and $fileVar are set (but are exclusive)" exit 1 fi local val="$def" if [ "${!var:-}" ]; then val="${!var}" elif [ "${!fileVar:-}" ]; then val="$(< "${!fileVar}")" fi export "$var"="$val" unset "$fileVar"}############################################################################ 运行mysqld --help --verbose --help 2>&1 >/dev/null命令,# 此命令会检查配置文件,若配置文件没问题,则成功,不成功则输出错误信息,及if中添# 加!取不成功。###########################################################################_check_config() { toRun=( "$@" --verbose --help ) if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then cat >&2 <<-EOM ERROR: mysqld failed while attempting to check config command was: "${toRun[*]}" $errors EOM exit 1 fi}# 1. $1参数为mysqld 以及 wanthelp 参数为空 以及root用户,执行此代码;# 2. _check_config检查配置文件是否正确# 3. 获取DATADIR目录,执行mysqld --verbose --help --log-bin-index=/tmp/tmp.4SyApJWeIo| \# awk '$1 == "'"datadir"'" { print $2; exit }'# 4. 创建并修改目录权限# 5. 执行exec gosu mysql docker-entrypoint.sh "$@",即重新以mysql用户再次调用脚# 本# allow the container to be started with `--user`if [ "$1" = 'mysqld' -a -z "$wantHelp" -a "$(id -u)" = '0' ]; then _check_config "$@" DATADIR="$(_get_config 'datadir' "$@")" mkdir -p "$DATADIR" chown -R mysql:mysql "$DATADIR" exec gosu mysql "$BASH_SOURCE" "$@"fi# 1. $1参数为mysqld 以及 wanthelp 参数为空,执行此代码,及exec gosu会执行此代码;if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then# 2. 仍然检查配置文件以及获取datadir目录 # still need to check config, container may have started with --user _check_config "$@" # Get config DATADIR="$(_get_config 'datadir' "$@")"# 3. 若mysql数据库未创建,则执行本段逻辑 if [ ! -d "$DATADIR/mysql" ]; then# 4. 检查是否设置变量,如root密码、允许root密码为空亦或者随机密码 file_env 'MYSQL_ROOT_PASSWORD' if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then echo >&2 'error: database is uninitialized and password option is not specified ' echo >&2 ' You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD' exit 1 fi# 5. 创建目录 mkdir -p "$DATADIR"# 6. 执行mysqld命令初始化数据库 echo 'Initializing database' "$@" --initialize-insecure echo 'Database initialized'# 7. command -v mysql_ssl_rsa_setup检查命令是否可执行,以及是否存在# server-key.pem文件,若不存在,则生成证书 if command -v mysql_ssl_rsa_setup > /dev/null && [ ! -e "$DATADIR/server-key.pem" ]; then # https://github.com/mysql/mysql-server/blob/23032807537d8dd8ee4ec1c4d40f0633cd4e12f9/packaging/deb-in/extra/mysql-systemd-start#L81-L84 echo 'Initializing certificates' mysql_ssl_rsa_setup --datadir="$DATADIR" echo 'Certificates initialized' fi# 8. 获取socket值并启动mysql SOCKET="$(_get_config 'socket' "$@")" "$@" --skip-networking --socket="${SOCKET}" & pid="$!"# 9. 设置mysql变量(列表形式),而后可以${mysql[@]}调用 mysql=( mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" )# 10. 运行30次,验证mysql是否已经启动完毕 for i in {30..0}; do if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then break fi echo 'MySQL init process in progress...' sleep 1 done# 11. 若i为0值,则表明mysql启动失败 if [ "$i" = 0 ]; then echo >&2 'MySQL init process failed.' exit 1 fi# 11. 解决时区bug if [ -z "$MYSQL_INITDB_SKIP_TZINFO" ]; then # sed is for https://bugs.mysql.com/bug.php?id=20545 mysql_tzinfo_to_sql /usr/share/zoneinfo | \ sed 's/Local time zone must be set--see zic manual page/FCTY/' | "${mysql[@]}" mysql fi# 12. 生成root随机密码 if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then export MYSQL_ROOT_PASSWORD="$(pwgen -1 32)" echo "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" fi# 13. 若MYSQL_ROOT_HOST不为空亦或者不为localhost,则创建root用户 rootCreate= # default root to listen for connections from anywhere file_env 'MYSQL_ROOT_HOST' '%' if [ ! -z "$MYSQL_ROOT_HOST" -a "$MYSQL_ROOT_HOST" != 'localhost' ]; then # no, we don't care if read finds a terminating character in this heredoc # https://unix.stackexchange.com/questions/265149/why-is-set-o-errexit-breaking-this-read-heredoc-expression/265151#265151 read -r -d '' rootCreate <<-EOSQL || true CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ; GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; EOSQL fi# 14. 为'root'@'localhost'重置root密码# 使用$rootCreate创建root "${mysql[@]}" <<-EOSQL -- What's done in this file shouldn't be replicated -- or products like mysql-fabric won't work SET @@SESSION.SQL_LOG_BIN=0; SET PASSWORD FOR 'root'@'localhost'=PASSWORD('${MYSQL_ROOT_PASSWORD}') ; GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION ; ${rootCreate} DROP DATABASE IF EXISTS test ; FLUSH PRIVILEGES ; EOSQL# 15. 已设置root密码,故mysql需加上root密码 if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then mysql+=( -p"${MYSQL_ROOT_PASSWORD}" ) fi# 16. 若配置了MYSQL_DATABASE变量,则创建 file_env 'MYSQL_DATABASE' if [ "$MYSQL_DATABASE" ]; then echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}" mysql+=( "$MYSQL_DATABASE" ) fi# 17. 在数据库内创建用户 file_env 'MYSQL_USER' file_env 'MYSQL_PASSWORD' if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then echo "CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;" | "${mysql[@]}" if [ "$MYSQL_DATABASE" ]; then echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;" | "${mysql[@]}" fi echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}" fi# 18. 执行/docker-entrypoint-initdb.d目录下面的脚本,包含shell、sql echo for f in /docker-entrypoint-initdb.d/*; do case "$f" in *.sh) echo "$0: running $f"; . "$f" ;; *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;; *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;; *) echo "$0: ignoring $f" ;; esac echo done# 19. 设置root密码是否过期 if [ ! -z "$MYSQL_ONETIME_PASSWORD" ]; then "${mysql[@]}" <<-EOSQL ALTER USER 'root'@'%' PASSWORD EXPIRE; EOSQL fi# 20. kill -s TERM "$pid" 杀掉mysql进程,执行成功则返回0,而!kill取反,即kill成# 功后才执行后面的!wait命令 if ! kill -s TERM "$pid" || ! wait "$pid"; then echo >&2 'MySQL init process failed.' exit 1 fi# 21. 初始化成功后,再次启动 echo echo 'MySQL init process done. Ready for start up.' echo fifi# 22. 正式启动数据库exec "$@"

June 28, 2019 · 4 min · jiezi

Openshift环境安装K8S软件管理工具Helm

参考: Make a Kubernetes Operator in 15 minutes with Helm;Deploy Monocular on OpenShift;Helm中文指南;使用Helm管理kubernetes应用;https://helm.sh/docs/using_he...;参考官方文档https://docs.helm.sh/using_he...,Openshift环境安装Helm Tiller时其指向Blog:https://blog.openshift.com/ge...: Helm works straightforward on OpenShift Online, OpenShift Dedicated, OpenShift Container Platform (version >= 3.6) or OpenShift Origin (version >= 3.6). To learn more read this blog post.安装helm客户端,版本参考https://github.com/helm/helm/...。如下所示,在m01主机安装当前最新文档版v2.12.3: cd /tmpcurl -s https://storage.googleapis.com/kubernetes-helm/helm-v2.12.3-linux-amd64.tar.gz \ | tar xzsudo mv linux-amd64/helm /usr/local/binsudo chmod a+x /usr/local/bin/helm可选。默认stable仓库为https://kubernetes-charts.sto...,但此网被墙导致无法连接,可删掉并添加其他第三方仓库,如: helm repo remove stable# 将阿里云仓库设置为stable仓库:helm init --client-only --stable-repo-url \ https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts # 或为仓库设置不同的名称:helm repo add ali-stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/chartshelm repo add ali-incubator \ https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com/charts-incubatorhelm repo add bitnami https://charts.bitnami.com/bitnamihelm repo list安装tiller: ...

June 28, 2019 · 1 min · jiezi

探究K8S-Service内部iptables路由规则

前言 在K8S集群内部,应用常使用Service互访,那么,了解Service技术优缺点将有利于应用规划与部署,鉴于此,本文将通过简单案例以探索Cluster-Ip类型Service服务的利弊。 为便于讲解,我们先创建如下应用及Service服务: # kubectl run --image=nginx nginx-web-1 --image-pull-policy='IfNotPresent'# kubectl expose deployment nginx-web-1 --port=80 --target-port=80Service探索 作者的K8S环境是1.9版本,其Service内部服务由Kube-Proxy1提供,且默认用iptables技术实现,故本文探索K8S集群Service技术,即研究iptables在K8S上的技术实现。 Service Route(服务路由) 如下可知,通过nginx-web-1服务可实际访问到后端pod: # nginx pod ip地址:# kubectl describe pod nginx-web-1-fb8d45f5f-dcbtt | grep "IP"IP: 10.129.1.22# Service服务,通过172.30.132.253:80则实际访问到10.129.1.22:80# kubectl describe svc nginx-web-1 ...Type: ClusterIPIP: 172.30.132.253Port: <unset> 80/TCPTargetPort: 80/TCPEndpoints: 10.129.1.22:80Session Affinity: None...# 重置nginx web页面:# kubectl exec -it nginx-web-1-fb8d45f5f-dcbtt -- \ sh -c "echo hello>/usr/share/nginx/html/index.html"# curl 10.129.1.22hello# curl 172.30.132.253hello Service服务分配的CLUSTER-IP以及监听的端口均虚拟的,即在K8S集群节点上执行ip a与netstat -an命令均无法找到,其实际上,IP与Port是由iptables配置在每K8S节点上的。在节点上执行如下命令可找到此Service相关的iptables配置,简析如下: 当通过Service服务IP:172.30.132.253:80访问时,匹配第3条规则链(KUBE-SERVICES)后,跳转到第4条子链(KUBE-SVC-...)上;第4条子链做简单注释后,继而跳转到第1、2规则链(KUBE-SEP-...)上;当源Pod通过Service访问自身时,匹配第1条规则,继而跳转到KUBE-MARK-MASQ链中;匹配到第2条规则,此时通过DNAT被重定向到后端Pod:108.29.1.22:80。# iptables-save | grep nginx-web-1-A KUBE-SEP-UWNFTKZFYWNNNTK7 -s 10.129.1.22/32 -m comment --comment "demo/nginx-web-1:" \ -j KUBE-MARK-MASQ-A KUBE-SEP-UWNFTKZFYWNNNTK7 -p tcp -m comment --comment "demo/nginx-web-1:" \ -m tcp -j DNAT --to-destination 10.129.1.22:80-A KUBE-SERVICES -d 172.30.132.253/32 -p tcp -m comment \ --comment "demo/nginx-web-1: cluster IP" -m tcp --dport 80 -j KUBE-SVC-SNP24T7IBBNZDJ76-A KUBE-SVC-SNP24T7IBBNZDJ76 -m comment --comment "demo/nginx-web-1:" \ -j KUBE-SEP-UWNFTKZFYWNNNTK7 详细分析iptables规则,执行iptables-save命令可发现nat的PREROUTING与OUTPUT链中均有KUBE-SERVICES规则链,且处于第一顺位。 ...

June 28, 2019 · 3 min · jiezi

kubernetes-常用命令缩容扩容回滚

查看版本kubectl version查看节点kubectl get nodes部署app说明: 提供deployment名称和app镜像地址(docker镜像地址) kubectl run kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --port=8080再如: run test --image=preparedman/mytomcat:tagname --port=8088查看appkubectl proxy测试:curl http://localhost:8001/version { "major": "1", "minor": "13", "gitVersion": "v1.13.3", "gitCommit": "721bfa751924da8d1680787490c54b9179b1fed0", "gitTreeState": "clean", "buildDate": "2019-02-01T20:00:57Z", "goVersion": "go1.11.5", "compiler": "gc", "platform": "linux/amd64"}获取pod名字 export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')测试:echo Name of the Pod: $POD_NAME 使用kubectl进行故障排除主要使用如下命令 kubectl get - list resources 列出资源kubectl describe - show detailed information about a resource 显示资源详情kubectl logs - print the logs from a container in a pod 打印`pod` 中container的日志kubectl exec - execute a command on a container in a pod 在`pod`中的container上执行命令获取应用配置查看应用是否在运行 ...

June 25, 2019 · 4 min · jiezi

如何使用curl访问k8s的apiserver

使用TOKEN授权访问api-server在k8s运维场景中比较常见, apiserver有三种级别的客户端认证方式 1,HTTPS证书认证:基于CA根证书签名的双向数字证书认证方式 2,HTTP Token认证:通过一个Token来识别合法用户 3,HTTP Base认证:通过用户名+密码的认证方式 通常的运维场景使用第二种Token较为方便Token的权限是关联service account, # kubectl describe secrets admin-token-2q28f -n kube-systemName: admin-token-2q28fNamespace: kube-systemLabels: <none>Annotations: kubernetes.io/service-account.name: admin kubernetes.io/service-account.uid: 93316ffa-7545-11e9-b617-00163e06992dType: kubernetes.io/service-account-tokenData====ca.crt: 1419 bytesnamespace: 11 bytestoken: eyJhbGciOiJ******Service Account 的权限来自Clusterrolebinding-->ClusterRole # kubectl describe serviceaccount admin -n kube-systemName: adminNamespace: kube-systemLabels: <none>Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"admin","namespace":"kube-system"}}Image pull secrets: <none>Mountable secrets: admin-token-2q28fTokens: admin-token-2q28fEvents: <none>通过clusterrolebinding 可以拿到ClusterRole对应的rolename # kubectl get clusterrolebinding admin -o yamlapiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"rbac.authorization.k8s.io/v1beta1","kind":"ClusterRoleBinding","metadata":{"annotations":{},"name":"admin"},"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"ClusterRole","name":"cluster-admin"},"subjects":[{"kind":"ServiceAccount","name":"admin","namespace":"kube-system"}]} creationTimestamp: 2019-05-13T06:08:49Z name: admin resourceVersion: "1523" selfLink: /apis/rbac.authorization.k8s.io/v1/clusterrolebindings/admin uid: 93356439-7545-11e9-b617-00163e06992droleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-adminsubjects:- kind: ServiceAccount name: admin namespace: kube-system这个role是什么权限? ...

June 24, 2019 · 2 min · jiezi

microk8s安装过程中遇到的几个问题

问题microk8s安装过程中,部分镜像需要从google的镜像仓库拉取,但是国内无法访问其镜像仓库, 故需要手动获取镜像再自行安装(从官方提供的google mirror仓库获取)microk8s不是使用的宿主机器的docker进程, 故不能简单的把自己获取的镜像重新tag来完成安装; 需要导出之后然后使用microk8s提供的镜像管理功能进行导入解决原理获取到你需要的镜像名称和版本之后 (参见后面的排查技巧) docker pull mirrorgooglecontainers/$imageName:$imageVersiondocker tag mirrorgooglecontainers/$imageName:$imageVersion k8s.gcr.io/$imageName:$imageVersiondocker save k8s.gcr.io/$imageName:$imageVersion > $imageName.tarmicrok8s.ctr -n k8s.io image import $imageName.tar示例步骤视你开启的插件而言,需要手动安装需要的镜像, 以我为例, 需要如下这些(注意版本可能不一样) k8s.gcr.io/pause:3.1k8s.gcr.io/heapster-influxdb-amd64:v1.3.3k8s.gcr.io/heapster-grafana-amd64:v4.4.3k8s.gcr.io/heapster-amd64:v1.5.2k8s.gcr.io/kubernetes-dashboard-amd64:v1.8.3gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.7gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.7gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.7安装脚本如下(可以根据原理做成通用脚本再传参安装): docker pull mirrorgooglecontainers/pause:3.1docker pull mirrorgooglecontainers/heapster-influxdb-amd64:v1.3.3docker pull mirrorgooglecontainers/heapster-grafana-amd64:v4.4.3docker pull mirrorgooglecontainers/kubernetes-dashboard-amd64:v1.8.3docker pull mirrorgooglecontainers/heapster-amd64:v1.5.2docker pull mirrorgooglecontainers/k8s-dns-dnsmasq-nanny-amd64:1.14.7docker pull mirrorgooglecontainers/k8s-dns-kube-dns-amd64:1.14.7docker pull mirrorgooglecontainers/k8s-dns-sidecar-amd64:1.14.7docker tag mirrorgooglecontainers/pause:3.1 k8s.gcr.io/pause:3.1docker tag mirrorgooglecontainers/heapster-influxdb-amd64:v1.3.3 k8s.gcr.io/heapster-influxdb-amd64:v1.3.3docker tag mirrorgooglecontainers/heapster-grafana-amd64:v4.4.3 k8s.gcr.io/heapster-grafana-amd64:v4.4.3docker tag mirrorgooglecontainers/kubernetes-dashboard-amd64:v1.8.3 k8s.gcr.io/kubernetes-dashboard-amd64:v1.8.3docker tag mirrorgooglecontainers/heapster-amd64:v1.5.2 k8s.gcr.io/heapster-amd64:v1.5.2docker tag mirrorgooglecontainers/k8s-dns-dnsmasq-nanny-amd64:1.14.7 gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.7docker tag mirrorgooglecontainers/k8s-dns-kube-dns-amd64:1.14.7 gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.7docker tag mirrorgooglecontainers/k8s-dns-sidecar-amd64:1.14.7 gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.7docker save k8s.gcr.io/pause > pause.tardocker save k8s.gcr.io/heapster-influxdb-amd64 > heapster-influxdb-amd64.tardocker save k8s.gcr.io/heapster-grafana-amd64 > heapster-grafana-amd64.tardocker save k8s.gcr.io/kubernetes-dashboard-amd64 > kubernetes-dashboard-amd64.tardocker save k8s.gcr.io/heapster-amd64 > heapster-amd64.tardocker save gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64 > k8s-dns-dnsmasq-nanny-amd64.tardocker save gcr.io/google_containers/k8s-dns-kube-dns-amd64 > k8s-dns-kube-dns-amd64.tardocker save gcr.io/google_containers/k8s-dns-sidecar-amd64 > k8s-dns-sidecar-amd64.tarmicrok8s.ctr -n k8s.io image import pause.tarmicrok8s.ctr -n k8s.io image import heapster-influxdb-amd64.tarmicrok8s.ctr -n k8s.io image import heapster-grafana-amd64.tarmicrok8s.ctr -n k8s.io image import kubernetes-dashboard-amd64.tarmicrok8s.ctr -n k8s.io image import heapster-amd64.tarmicrok8s.ctr -n k8s.io image import k8s-dns-dnsmasq-nanny-amd64.tarmicrok8s.ctr -n k8s.io image import k8s-dns-kube-dns-amd64.tarmicrok8s.ctr -n k8s.io image import k8s-dns-sidecar-amd64.tar排查技巧遇到问题时先通过 microk8s.kubectr get pods 查看是否是RUNNING状态, 如果不是,先按照上述方法解决镜像问题查看具体的镜像版本时候可以通过 kubectl get pods --namespace=kube-system -o json |grep message直接过滤出错误消息注意namespace的选择, 特别是你自己定义了namespace之后

June 20, 2019 · 1 min · jiezi

Kubernetes-115可扩展性和持续改进

作者:1.15发布团队 我们很高兴地宣布交付Kubernetes 1.15,这是我们2019年的第二个版本!Kubernetes 1.15包含25个增强:2个升级为稳定,13个升级为beta,10个升级为alpha。这次发布的主题是: 持续改进 项目的可持续性不仅仅是功能。许多SIG一直致力于提高测试覆盖率,确保基本功能保持可靠,确保核心功能集的稳定性,并致力于成熟现有功能和清理积压。可扩展性 社区一直要求继续支持可扩展性,因此这个周期围绕CRD和API Machinery进行更多的工作。这个周期中的大多数增强来自SIG API Machinery和相关领域。让我们深入了解这个版本的主要特性: 围绕核心Kubernetes API的可扩展性围绕customresourcedefinition的新开发的主题是数据一致性和原生行为。用户不应该注意交互是与CustomResource还是与Golang-native资源进行的。随着大的步骤,我们在未来的版本之一正在努力向一个GA版本的CRD和GA的准入webhook。 在这个方向上,我们重新考虑了CRD中基于OpenAPI的验证模式,从1.15开始,我们根据“结构模式(structural schema)”的限制检查每个模式。这基本上强制了CustomResource中每个字段的非多态( non-polymorphic)和完整类型(complete typing)。将来我们将需要结构模式,特别是对于所有新特性,包括下面列出的特性,以及列出非结构(NonStructural)条件下的违规行为。在v1beta1 API组中,非结构模式(non-structural schema)仍然保持工作状态。但是任何严肃的CRD应用程序都应该在可预见的将来迁移到结构模式。 关于什么使模式结构化的详细信息将在kubernetes.io的博客文章中在本周晚些时候发布,当然Kubernetes的文档中对此有记录。 beta: CustomResourceDefinition Webhook Conversioncustomresourcedefinition自1.14起作为beta支持多个版本。使用Kubernetes 1.15,它们能够实时地在不同版本之间进行转换,就像用户长期习惯于从原生资源进行转换一样。CRD的转换是通过webhook实现的,由集群管理员部署在集群内部。这一特性已在Kubernetes 1.15中升级到beta,将CRD提升到一个全新的水平,用于真正的CRD应用程序。 beta: CustomResourceDefinition OpenAPI Publishingkube-apiserver在/openapi/v2上为原生类型提供OpenAPI规范已经有很长一段时间了,它们被许多组件使用,尤其是kubectl客户端验证、kubectl explain和基于OpenAPI的客户端生成器。 用于CRD的OpenAPI发布将在Kubernetes 1.15作为beta提供,同样只适用于结构模式。 beta: CustomResourceDefinitions Pruning修剪(Pruning)是自动删除发送到Kubernetes API的对象中的未知字段。如果未在OpenAPI验证模式中指定字段,则该字段是未知的。这是一个数据一致性和安全性相关的特性。它强制只将CRD开发者指定的数据结构持久化到etcd。这是原生资源的行为,也将用于CRD,从Kubernetes 1.15的beta版开始。 修剪是通过CustomResourceDefinition中的spec.preserveUnknownFields: false激活。将来的apiextensions.k8s.io/v1 CRD变种将强制执行修剪(可能但明确必要的选择退出)。 修剪要求CRD开发者为CRD的所有版本提供完整的、结构化的验证模式,要么是顶层的,要么是所有版本的。 alpha: CustomResourceDefinition Defaultingcustomresourcedefinition获得默认支持。默认值是使用OpenAPI验证模式中的default关键字指定的。在发送到API的对象中以及从etcd读取时,为未指定字段设置默认值。 default在Kubernetes 1.15中将作为alpha提供,用于结构模式。 beta: Admission Webhook Reinvocation & Improvements对于扩展Kubernetes API的项目来说,变异(mutating)和验证(validating)准入(admission)webhook变得越来越主流。到目前为止,按照字母顺序,只调用了一次变异webhook。早期运行的webhook不能对链中稍后调用的webhook的输出作出反应。随着Kubernetes 1.15的发布,情况将发生变化: 通过指定reinvocationPolicy: ifNeeded,变异webhook可以选择至少一次重新调用。如果后面的变异webhook修改了对象,那么前面的webhook将得到第二次机会。 这要求webhook具有类似幂等(idempotent)的行为,可以处理第二次调用。 不打算添加另一轮调用,这样webhook的作者仍然必须小心对他们实现的已被承认的对象的更改。最后,调用验证webhook来验证所承诺的不变量是否已实现。 对准入webhook有更多更小的更改,特别是objectSelector,它将具有特定标签的对象排除在准入之外,以及webhook服务器的任意端口(不仅仅是443)。 集群生命周期的稳定性和可用性的改进使Kubernetes的安装、升级和配置更加健壮是SIG Cluster Lifecycle在这个周期的主要关注点(请参阅我们的社区近况)。跨裸金属工具的Bug修复和生产就绪的用户场景(如高可用性用例)在1.15中获得优先级。 集群生命周期构建块kubeadm继续接收高效引导生产集群所需的特性和稳定性工作。kubeadm将高可用性(high availability,HA)功能提升到了beta,允许用户使用熟悉的kubeadm init和kubeadm join命令来配置和部署HA控制平面。已经专门创建了一个全新的测试套件,以确保这些特性在一段时间内保持稳定。 ...

June 20, 2019 · 1 min · jiezi

kubernetes中的local-persistent-volume

什么是Local Persistent Volumes在kubernetes 1.14版本中, Local Persistent Volumes(以下简称LPV)已变为正式版本(GA),LPV的概念在1.7中被首次提出(alpha),并在1.10版本中升级到beat版本。现在用户终于可以在生产环境中使用LPV的功能和API了。 首先:Local Persistent Volumes代表了直接绑定在计算节点上的一块本地磁盘。 kubernetes提供了一套卷插件(volume plugin)标准,使得k8s集群的工作负载可以使用多种块存储和文件存储。大部分磁盘插件都使用了远程存储,这是为了让持久化的数据与计算节点彼此独立,但远程存储通常无法提供本地存储那么强的读写性能。有了LPV 插件,kubernetes负载现在可以用同样的volume api,在容器中使用本地磁盘。 这跟hostPath有什么区别hostPath是一种volume,可以让pod挂载宿主机上的一个文件或目录(如果挂载路径不存在,则mkdir创建为目录并挂载)。 最大的不同在于调度器能理解磁盘和node的对应关系,一个使用hostPath的pod,当他被重新调度时,很有可能被调度到与原先不同的node上,这就导致pod内数据丢失了。而使用LPV的pod,总会被调度到同一个node上(否则就调度失败)。 如何使用LPV首先 需要创建StorageClass kind: StorageClassapiVersion: storage.k8s.io/v1metadata: name: local-storageprovisioner: kubernetes.io/no-provisionervolumeBindingMode: WaitForFirstConsumer注意到这里volumeBindingMode字段的值是WaitForFirstConsumer。这种bindingmode意味着: kubernetes的pv控制器会将这类pv的binding或provisioning(可以理解为动态create)延迟,直到有一个使用了对应pvc的pod被创建出来且该pod被调度完毕。这时候才会将pv和pvc进行binding,并且这时候pv的选择会结合调度的node和pv的nodeaffinity。 接下来,提前准备好的provisioner会动态创建PV。 $ kubectl get pvNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGElocal-pv-27c0f084 368Gi RWO Delete Available local-storage 8slocal-pv-3796b049 368Gi RWO Delete Available local-storage 7slocal-pv-3ddecaea 368Gi RWO Delete Available local-storage 7sLPV的详细内容如下: $ kubectl describe pv local-pv-ce05be60 Name: local-pv-ce05be60Labels: <none>Annotations: pv.kubernetes.io/provisioned-by=local-volume-provisioner-minikube-18f57fb2-a186-11e7-b543-080027d51893StorageClass: local-fastStatus: AvailableClaim: Reclaim Policy: DeleteAccess Modes: RWOCapacity: 1024220KiNodeAffinity: Required Terms: Term 0: kubernetes.io/hostname in [my-node]Message: Source: Type: LocalVolume (a persistent volume backed by local storage on a node) Path: /mnt/disks/vol1Events: <none>当然,也可以不使用provisioner,而是手动创建PV。但是必须要注意的是,LPV必须要填写nodeAffinity。 ...

June 13, 2019 · 2 min · jiezi

使用kubeadm部署k8s测试环境centos7

零、3个节点基本信息如下:| ip | hostname | 用途 || 172.16.180.251 | k8s-master | master 节点 || 172.16.180.252 | k8s-node1 | node 节点1 || 172.16.180.253 | k8s-node2 | node 节点2 | 一、系统设置及资源准备这部分三个节点都需要进行配置和准备,当然node节点部分资源可以不下载,将不需要的部分剔除即可。这里为了方便就统一都一样处理吧 0、配置selinux和firewalld# Set SELinux in permissive modesetenforce 0sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config# Stop and disable firewalldsystemctl disable firewalld --now1、系统参数与内核模块# 修改内核参数cat <<EOF > /etc/sysctl.d/k8s.confnet.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1EOFsysctl --system# 加载内核模块modprobe br_netfilterlsmod | grep br_netfilter2、配置yum源# base repocd /etc/yum.repos.dmv CentOS-Base.repo CentOS-Base.repo.bakcurl -o CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.reposed -i 's/gpgcheck=1/gpgcheck=0/g' /etc/yum.repos.d/CentOS-Base.repo# docker repocurl -o docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo# k8s repocat <<EOF > /etc/yum.repos.d/kubernetes.repo[kubernetes]name=Kubernetesbaseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64enabled=1gpgcheck=0repo_gpgcheck=0gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpgEOF# update cacheyum clean all yum makecache yum repolist3、禁用swapswapoff -aecho "vm.swappiness = 0">> /etc/sysctl.confsysctl -p如果重启后swap又会被挂上,还需要注释掉/etc/fstab中的一行配置: ...

June 13, 2019 · 2 min · jiezi

干货-TiDB-Operator实践

K8s和TiDB都是目前开源社区中活跃的开源产品,TiDBOperator项目是一个在K8s上编排管理TiDB集群的项目。本文详细记录了部署K8s及install TiDBOperator的详细实施过程,希望能对刚"入坑"的同学有所帮助。一、环境Ubuntu 16.04K8s 1.14.1 二、Kubespray安装K8s配置免密登录1 yum -y install expectvi /tmp/autocopy.exp 1 #!/usr/bin/expect 2 3 set timeout 4 set user_hostname [lindex $argv ] 5 set password [lindex $argv ] 6 spawn ssh-copy-id $user_hostname 7 expect { 8 "(yes/no)?" 9 {10 send "yes\n"11 expect "*assword:" { send "$password\n"}12 }13 "*assword:"14 {15 send "$password\n"16 }17 }18 expect eof 1 ssh-keyscan addedip >> ~/.ssh/known_hosts 2 3 ssh-keygen -t rsa -P '' 4 5 for i in 10.0.0.{31,32,33,40,10,20,50}; do ssh-keyscan $i >> ~/.ssh/known_hosts ; done 6 7 /tmp/autocopy.exp root@addeip 8 ssh-copy-id addedip 910 /tmp/autocopy.exp root@10.0.0.3111 /tmp/autocopy.exp root@10.0.0.3212 /tmp/autocopy.exp root@10.0.0.3313 /tmp/autocopy.exp root@10.0.0.4014 /tmp/autocopy.exp root@10.0.0.1015 /tmp/autocopy.exp root@10.0.0.2016 /tmp/autocopy.exp root@10.0.0.50配置Kubespray1 pip install -r requirements.txt2 cp -rfp inventory/sample inventory/myclusterinventory/mycluster/inventory.iniinventory/mycluster/inventory.ini 1 # ## Configure 'ip' variable to bind kubernetes services on a 2 # ## different ip than the default iface 3 # ## We should set etcd_member_name for etcd cluster. The node that is not a etcd member do not need to set the value, or can set the empty string value. 4 [all] 5 # node1 ansible_host=95.54.0.12 # ip=10.3.0.1 etcd_member_name=etcd1 6 # node2 ansible_host=95.54.0.13 # ip=10.3.0.2 etcd_member_name=etcd2 7 # node3 ansible_host=95.54.0.14 # ip=10.3.0.3 etcd_member_name=etcd3 8 # node4 ansible_host=95.54.0.15 # ip=10.3.0.4 etcd_member_name=etcd4 9 # node5 ansible_host=95.54.0.16 # ip=10.3.0.5 etcd_member_name=etcd510 # node6 ansible_host=95.54.0.17 # ip=10.3.0.6 etcd_member_name=etcd611 etcd1 ansible_host=10.0.0.31 etcd_member_name=etcd112 etcd2 ansible_host=10.0.0.32 etcd_member_name=etcd213 etcd3 ansible_host=10.0.0.33 etcd_member_name=etcd314 master1 ansible_host=10.0.0.4015 node1 ansible_host=10.0.0.1016 node2 ansible_host=10.0.0.2017 node3 ansible_host=10.0.0.501819 # ## configure a bastion host if your nodes are not directly reachable20 # bastion ansible_host=x.x.x.x ansible_user=some_user2122 [kube-master]23 # node124 # node225 master126 [etcd]27 # node128 # node229 # node330 etcd131 etcd232 etcd33334 [kube-node]35 # node236 # node337 # node438 # node539 # node640 node141 node242 node34344 [k8s-cluster:children]45 kube-master46 kube-node节点所需镜像的文件由于某些镜像国内无法访问需要现将镜像通过代理下载到本地然后上传到本地镜像仓库或DockerHub,同时修改配置文件,个别组件存放位置https://storage.googleapis.com,需要新建Nginx服务器分发文件。 ...

June 11, 2019 · 5 min · jiezi

容器监控实践Grafana

概述Grafana 是一个开源的,可以用于大规模指标数据的可视化项目,甚至还能对指标进行报警。基于友好的 Apache License 2.0 开源协议,目前是prometheus监控展示的首选。优点如下: 1.使用:配置方便:支持Dashboard、Panel、Row等组合,且支持折线图、柱状图等多种图例图表漂亮:可以选择暗黑系或纯白系,你也可以自己定义颜色模板很多:grafana模板很活跃,有很多用户贡献的面板,直接导入就能用支持多种数据源:grafana作为展示面板,支持很多数据源,如Graphite、ES、Prometheus等权限管理简单:有admin、viewer等多种角色管控2.二次开发:如果默认的grafana不能满足你的需求,要二次开发,官方也提供了很多支持: 协议为Apache License 2.0:商业友好,随便改吧,改完拿去卖也行。完善的API调用:权限、面板、用户、报警都支持api调用。多种鉴权方式:OAuth、LADP、Proxy多种方式,你可以接入自己公司的鉴权系统插件开发:如果你不想直接改代码,可以做自己的插件go+Angular+react:常用的技术栈,方便二次开发prometheus + grafana 做为监控组合很方便,很强大,改造了鉴权之后更加香。一开始我们还尝试使用grafana自带的报警功能,可惜比较鸡肋,无法用于生产,报警的issue一大堆官方也不想修改,作罢 部署步骤一:安装grafana Grafana提供了很多种部署方式,如果你的展示报警是在K8S集群外,可以二进制直接部署,如果grafana本身在集群内,或者管理端也是k8s集群,可以用yaml部署: Deployment配置: apiVersion: apps/v1kind: Deploymentmetadata: namespace: kube-system name: grafanaspec: replicas: 1 selector: matchLabels: app: grafana template: metadata: namespace: kube-system annotations: grafana-version: '1.0' name: grafana labels: app: grafana spec: containers: - name: grafana image: grafana/grafana:5.1.0 imagePullPolicy: Always securityContext: runAsUser: 0 env: - name: GF_SECURITY_ADMIN_PASSWORD value: "admin" ports: - name: grafana containerPort: 3000 resources: requests: memory: "100Mi" cpu: "100m" limits: memory: "2048Mi" cpu: "1024m"Service配置: ...

June 6, 2019 · 2 min · jiezi

容器监控实践Dockbix

一.概述Dockbix意为docker+zabbix,即使用zabbix来监控docker容器的插件或者模块,既然有专业的cadvisor、prometheus等容器监控方案,为什么还要用传统的zabbix呢? 在docker刚出现时,还没有专业的容器监控方案公司已有zabbix的成熟实践,想直接集成到zabbix中(虽然不太优雅)使用zabbix来监控docker有几种方案,比如: 自己写agent,利用docker的api获取stats信息,暴露api接口给zabbix采集使用zabbix的Module,将docker的采集展示集成到现有的zabbix系统中如何使用写APIpython sdk:https://docker-py.readthedocs.io/en/stable/containers.html#docker.models.containers.Container.stats stats(**kwargs)Stream statistics for this container. Similar to the docker stats command.Parameters: decode (bool) – If set to true, stream will be decoded into dicts on the fly. Only applicable if stream is True. False by default.stream (bool) – If set to false, only the current stats will be returned instead of a stream. True by default.Raises: docker.errors.APIError – If the server returns an error.如计算cpu: ...

May 27, 2019 · 1 min · jiezi

初试k8s自顶向下的学习kubernetes

之前就玩过docker,但是一直不知道怎么把容器运用到生产上。构建一个docker镜像,把他run起来很简单;难的是容器的部署(CICD),容器的网络,数据持久化等。如果我们像之前一样,打包好镜像,通过ssh连接到目标服务器run起来,这和打包成二进制传上去似乎也没多大进步。 k8s就是帮我们解决这些难点的工具。k8s是master-node架构,通过master管理node。首先需要将你的机器组成k8s集群,集群机器的内网应该是连通的,这样你的集群就捆绑成了一个整体由k8s接管了。你只需要准备好配置文件,用k8s的api或cli(命令行)发布镜像即可,k8s会根据你配置的规则来管理容器,应用场景有:一份镜像需要部署多少个容器(replicaSets),服务的升级策略(滚动更新),服务的容灾策略(某个node挂了可以在其他node补上缺失的容器),弹性伸缩(监控CPU等指标达到临界值后自动增加容器)等。 怎么样?是不是觉得很cool,你可能迫不及待的想去把k8s用起来了,可是你打开k8s官方文档大段大段的英文和各种生疏的概念就把你整懵了。你跟着教程敲了一遍,一大堆yaml配置,全是命令行操作,可能你已经被墙给干倒了(天朝ha);还有一堆概念,什么Pod, Deployment, ReplicaSet, Service都是些啥玩意。可能你花了大半天耐心的把文档过了一遍,觉得这个东西根本落不了地啊,这一大堆配置和命令行,这谁顶得住,k8s这么先进不应该是可视化的点点就完事了吗?我一开始天真的以为k8s dashboard能帮帮我,费了点力气把它装好后,发现只有一些监控数据。 下面我想介绍另一种学习思路,自顶向下的学习。其实你一开始不用了解k8s的各种概念,只需要看看别人是怎么用k8s的就行了(都9102年了,那些很潮的公司都已经玩了很久了)。不是说学东西必须得打好基础吗?自顶向下是个什么鬼?拿学开车举例,你开始只是在路上看到别人开车,很拉风可撩妹,比两轮的安全,不怕风吹雨打的,教练我也要开车;你去报了驾校(看到这里你肯觉得我要忽悠你报培训班),你摸到了车看到别人是咋开的,了解了基本知识你就可以在训练场地慢慢蠕动了(测试环境),你甚至不用了解交规,更不用了解汽车的原理,这些后面可以慢慢补。补好基础了你就可以上路,然后你可能需要了解汽车原理,改装它优化它,再练一练排水渠过弯的技巧,成为一代老司机。 回到正题,我们学k8s同样可以先看看别人是咋用的,再去了解其中细节,掌握它。咋看呢?一大部分公司还没跟上潮流,这时我们可以借助开源和云服务。首先我们的思路没有问题,要便捷的使用k8s我们需要一个可视化管理平台。开源的有rancher、Qihoo360/wayne等,云服务阿里云、腾讯云、AWS都提供容器服务管理后台。 这里就拿rancher开始吧,毕竟开源免费。值得一提的是,阿里云等的容器服务按量积分,master可托管,弄一两天低配node,一天也就几块。 在本地启动rancher容器: sudo docker run -d --restart=unless-stopped -p 8080:80 -p 8443:443 rancher/rancher打开https://127.0.0.1:8443平台,可以看到cluster, node, namespace, member等功能。 下面我们需要准备一个k8s cluster(集群),用minikube可以方便的部署一个本地集群。minikube是通过虚拟机创建集群,支持多种虚拟机,我这里用的virtualBox。启动很简单,一个命令minikube start,困难的是墙,下面贴一下配置代理的脚本: function ministart() { export HTTP_PROXY=http://192.168.99.1:1089 export HTTPS_PROXY=http://192.168.99.1:1089 export NO_PROXY=localhost,127.0.0.1,10.96.0.0/12,192.168.99.0/24,192.168.39.0/24 minikube start \ --docker-env=HTTP_PROXY=$HTTP_PROXY \ --docker-env=HTTPS_PROXY=$HTTPS_PROXY \ --docker-env=NO_PROXY=$NO_PROXY \ --registry-mirror=https://registry.docker-cn.com}注意一下这个ip,不能使用127.0.0.1,因为虚拟机需要使用宿主的代理,虚拟机跟宿主机通讯是使用虚拟网卡创建的网段,默认宿主的ip为192.168.99.1,虚拟机是192.168.99.100。你还得把你的梯子监听的地址改改,127.0.0.1->0.0.0.0,监听所有网卡。同样rancher里的ip也应使用192.168.99.1,这个ip必需是所有集群都能访问到的,如果你是用docker自带的k8s集群,你可以用ifconfig找一个无线网或有线网的ip,反正不能使用127.0.0.1。 minikube下载一些必需镜像后,k8s集群就在虚拟机里启动了,可以使用minikube ssh登录到虚拟机里探查一番。下面我们在rancher里引入集群: 集群引入了之后我们来部署我们第一个app,一个echo-server: 等了一会儿k8s把容器部署好了,上面配置了暴露随机端口值是32192,我们访问192.168.99.100:32192就能看的echo-sever返回的信息了。我们觉得一个pod不够,点击+号,k8s会帮我们做水平扩容启动第二个pod,虽然minikube是但节点的,但是依靠容器的隔离特性,单节点照样能部署多个相同应用。 体验一下rancher的pipline功能,集成了CICD功能,配置好代码仓库后run起来,会启动一个jenkins pod来处理构建,还会建一个内置的镜像仓库,还有个minio存储pod,大概是用来存镜像的。等了好一会儿后,可以看到workloads里example-server部署好了。jenkins和registry都集成了好像挺方便,不过这个镜像如何持久化呢? ok,下面自行探索一下rancher平台提供的一些页面,有workloads,load blance,service discory,pipline这些部署常用的,还提供报警、日志、监控、用户权限等功能,这就是一个完善的k8s管理平台了,到此你应该了解k8s大概有哪些用处了。 下面你需要再把k8s官方文档捡起来看一看,或者是一本系统介绍k8s的书籍,把你在rancher上用到的功能和k8s的概念对应起来,现在你才能抓住哪些是重点。 一些概念:pod:k8s最小调度单位,可以是一个或多个容器。 service:对内或对外暴露k8s服务。 deployment:pods和replicaSets的控制器,通过deployment配置的规则来管理pods。 三个主要的命令行程序:kubeadm:用了启动k8s集群。 kubelet:需要在所以节点上运行,处理集群内部通讯,类似agent。 ...

May 27, 2019 · 1 min · jiezi

dockerk8s云

在https://segmentfault.com/a/11... 容器,隔离,云的概述。这篇对其中用途广泛的docker,k8s做详细介绍,并给出云搭建的生态环境体系。 docker1.与其他VM等对比容器发展,详见上面提到的文章 chroot1979Linux Vserver2001process container2006LXC2008Docker2013windows container2017典型图:VM与container对比,差异在于OS VMcontainer隔离OSkernel namespace可配额,可度量硬件页映射cgroups移动性snapshot,imageAUFS安全 gresc patch缺点 隔离性相比KVM之类的虚拟化方案还是有些欠缺,所有container公用一部分的运行库网络管理相对简单,主要是基于namespace隔离cgroup的cpu和cpuset提供的cpu功能相比KVM的等虚拟化方案相比难以度量(所以dotcloud主要是安内存收费)docker对disk的管理比较有限(disk quota)container随着用户进程的停止而销毁,container中的log等用户数据不便收集 优点: 轻量级的特点,其启动快,而且docker能够只加载每个container变化的部分,这样资源占用小docker不只是容器,高级容器引擎,应用部署平台,应用镜像商店2.docker生态圈————不只是容器 Image 一个包含运行环境的只读 模板Container 镜像的运行态,docker利 用容器运行应用Registry 存储容器镜像的仓库Dockerfile 包含构建镜像一系列命令 和参数的脚本3.执行过程 Docker Daemon 可以认为是通过 Docker Server 模块接受 Docker Client 的请求,并在 Engine 中处理请求,然后根据请求类型,创建出指定的 Job 并运行。 Docker Daemon 运行在 Docker host 上,负责创建、运行、监控容器,构建、存储镜像。job运行过程的作用有以下几种可能:向 Docker Registry 获取镜像通过 graphdriver 执行容器镜像的本地化操作启动容器graphGraph在Docker架构中扮演已下载容器镜像的保管者,以及已下载容器镜像之间关系的记录者。一方面,Graph存储着本地具有版本信息的文件系统镜像,另一方面也通过GraphDB记录着所有文件系统镜像彼此之间的关系。GraphDB是一个构建在SQLite之上的小型图数据库,实现了节点的命名以及节点之间关联关系的记录。它仅仅实现了大多数图数据库所拥有的一个小的子集,但是提供了简单的接口表示节点之间的关系。Graph的本地目录中,关于每一个的容器镜像,具体存储的信息有:该容器镜像的元数据,容器镜像的大小信息,以及该容器镜像所代表的具体rootfs。networkdriver 执行容器网络环境的配置networkdriver的用途是完成Docker容器网络环境的配置,其中包括Docker启动时为Docker环境创建网桥;Docker容器创建时为其创建专属虚拟网卡设备;以及为Docker容器分配IP、端口并与宿主机做端口映射,设置容器防火墙策略等。execdriver 执行容器内部运行的执行工作execdriver作为Docker容器的执行驱动,负责创建容器运行命名空间,负责容器资源使用的统计与限制,负责容器内部进程的真正运行等。在execdriver的实现过程中,原先可以使用LXC驱动调用LXC的接口,来操纵容器的配置以及生命周期,而现在execdriver默认使用native驱动,不依赖于LXC。具体体现在Daemon启动过程中加载的ExecDriverflag参数,该参数在配置文件已经被设为"native"。这可以认为是Docker在1.2版本上一个很大的改变,或者说Docker实现跨平台的一个先兆libcontainerDocker架构中一个使用Go语言设计实现的库,设计初衷是希望该库可以不依靠任何依赖,直接访问内核中与容器相关的API。正是由于libcontainer的存在,Docker可以直接调用libcontainer,而最终操纵容器的namespace、cgroups、apparmor、网络设备以及防火墙规则等。这一系列操作的完成都不需要依赖LXC或者其他包。libcontainer提供了一整套标准的接口来满足上层对容器管理的需求。 docker run过程(1) Docker Client接受docker run命令,解析完请求以及收集完请求参数之后,发送一个HTTP请求给Docker Server,HTTP请求方法为POST,请求URL为/containers/create? +xxx;(2) Docker Server接受以上HTTP请求,并交给mux.Router,mux.Router通过URL以及请求方法来确定执行该请求的具体handler;(3) mux.Router将请求路由分发至相应的handler,具体为PostContainersCreate;(4) 在PostImageCreate这个handler之中,一个名为"create"的job被创建,并开始让该job运行;(5) 名为"create"的job在运行过程中,执行Container.Create操作,该操作需要获取容器镜像来为Docker容器创建rootfs,即调用graphdriver;(6) graphdriver从Graph中获取创建Docker容器rootfs所需要的所有的镜像;(7) graphdriver将rootfs所有镜像,加载安装至Docker容器指定的文件目录下;(8) 若以上操作全部正常执行,没有返回错误或异常,则Docker Client收到Docker Server返回状态之后,发起第二次HTTP请求。请求方法为"POST",请求URL为"/containers/"+container_ID+"/start";(9) Docker Server接受以上HTTP请求,并交给mux.Router,mux.Router通过URL以及请求方法来确定执行该请求的具体handler;(10) mux.Router将请求路由分发至相应的handler,具体为PostContainersStart;(11) 在PostContainersStart这个handler之中,名为"start"的job被创建,并开始执行;(12) 名为"start"的job执行完初步的配置工作后,开始配置与创建网络环境,调用networkdriver;(13) networkdriver需要为指定的Docker容器创建网络接口设备,并为其分配IP,port,以及设置防火墙规则,相应的操作转交至libcontainer中的netlink包来完成;(14) netlink完成Docker容器的网络环境配置与创建;(15) 返回至名为"start"的job,执行完一些辅助性操作后,job开始执行用户指令,调用execdriver;(16) execdriver被调用,初始化Docker容器内部的运行环境,如命名空间,资源控制与隔离,以及用户命令的执行,相应的操作转交至libcontainer来完成;(17) libcontainer被调用,完成Docker容器内部的运行环境初始化,并最终执行用户要求启动的命令。4.docker技术 ...

May 14, 2019 · 3 min · jiezi

kubescheduler调度扩展

Kubernetes 自带了一个默认调度器kube-scheduler,其内置了很多节点预选和优选的调度算法,一般调度场景下可以满足要求。但是在一些特殊场景下,默认调度器不能满足我们复杂的调度需求。我们就需要对调度器进行扩展,以达到调度适合业务场景的目的。 背景 中间件redis容器化后,需要两主不能在同一个节点上,一对主从不能在同一节点上;elasticsearch容器化后,两个data实例不能在同一节点上。在这类场景下,默认调度器内置的预选、优选算法不能满足需求,我们有以下三种选择: 将新的调度算法添加到默认调度程序中,并重新编译镜像,最终该镜像运行的实例作为kubernetes集群调度器; 参考kube-scheduler实现满足自己业务场景的调度程序,并编译镜像,将该程序作为独立的调度器运行到kubernetes集群内,需要用该调度器调度的pod实例,在spec.schedulerName里指定该调度器; image实现“调度扩展程序“:默认调度器kube-scheduler在进行预选时会调用该扩展程序进行过滤节点;在优选时会调用该扩展程序进行给节点打分,或者在bind操作时,调用该扩展器进行bind操作。 对上述三种方式进行评估: 第一种:将自己的调度算法添加到默认调度器kube-scheduler中,对原生代码侵入性较高,而且随着kubernetes版本升级,维护成本也较高; 第二种:默认调度器里内置了很多优秀调度算法,如:检查节点资源是否充足;端口是否占用;volume是否被其他pod挂载;亲和性;均衡节点资源利用等,如果完全使用自己开发的调度器程序,可能在达到了实际场景调度需求同时,失去更佳的调度方案,除非集成默认调度器中的算法到自己独立调度程序中,但这无疑是不现实的; 第三种:通过启动参数的policy配置,选用某些默认调度器中的预选、优选调度算法的同时,也可以调用外部扩展调度程序的算法,计算得到最优的调度节点,无需修改kube-scheduler代码,只需要在启动参数中增加配置文件即可将默认调度程序和扩展调度程序相互关联。 可以参考: https://github.com/kubernetes... 故采用第三种:实现扩展调度程序的方案。 整体架构 imagekube-scheduler在调度pod实例时,首先获取到Node1、Node2、Node3三个节点信息,进行默认的预选阶段,筛选满足要求的节点,其次再调用扩展程序中的预选算法,选出剩下的节点,假设预选阶段Node3上资源不足被过滤掉,预选结束后只剩Node1和Node2;Node1和Node2进入kube-scheduler默认的优选阶段进行节点打分,其次再调用扩展调度程序中的优选算法进行打分,kube-scheduler会将所有算法的打分结果进行加权求和,获得分数最高的节点作为pod最终bind节点,然后kube-scheduler调用apiserver进行bind操作。 实现步骤 实现扩展调度程序代码 编写扩展调度器程序代码,根据实际业务调度场景编写预选逻辑、优选逻辑: image实现预选接口,入参为schedulerapi.ExtenderArgs,出参为schedulerapi.ExtenderFilterResult: image实现优选接口,入参为schedulerapi.ExtenderArgs,出参为schedulerapi.HostPriorityList: image暴露http接口: image参考: https://github.com/ll83744879... 默认调度器部署 由于kubernetes集群内已经有了一个名为default-scheduler的默认调度器,为了不影响集群正常调度功能,下面会创建一个名为my-kube-scheduler的调度器,这个调度器和default-scheduler除了启动参数不一样外,镜像无差别。 1、创建一个名为my-scheduler-config的configmaps,data下的config.yaml文件指定了调度器的一些参数,包括leader选举,调度算法策略的选择(指定另一个configmaps),以及指定调度器的名称为my-kube-scheduler。 相应的创建一个my-scheduler-policy的configmaps,里面指定了选择哪些预选、优选策略,以及外部扩展调度程序的urlPrefix、扩展预选URI、扩展优选URI、扩展pod优先级抢占URI、扩展bind URI、扩展优选算法的权重等。 以保证my-kube-scheduler和扩展调度程序的通信。 apiVersion: v1kind: ConfigMapmetadata: name: my-scheduler-config namespace: kube-systemdata: config.yaml: | apiVersion: kubescheduler.config.k8s.io/v1alpha1kind: KubeSchedulerConfigurationschedulerName: my-kube-scheduleralgorithmSource: policy: configMap: namespace: kube-system name: my-scheduler-policyleaderElection: leaderElect: false lockObjectName: my-kube-scheduler lockObjectNamespace: kube-systemapiVersion: v1kind: ConfigMapmetadata: name: my-scheduler-policy namespace: kube-systemdata: policy.cfg : | { "kind" : "Policy","apiVersion" : "v1","predicates" : [ {"name" : "PodFitsHostPorts"}, {"name" : "PodFitsResources"}, {"name" : "NoDiskConflict"}, {"name" : "MatchNodeSelector"}, {"name" : "HostName"}],"priorities" : [ {"name" : "LeastRequestedPriority", "weight" : 1}, {"name" : "BalancedResourceAllocation", "weight" : 1}, {"name" : "ServiceSpreadingPriority", "weight" : 1}, {"name" : "EqualPriority", "weight" : 1}],"extenders" : [{ "urlPrefix": "http://10.168.107.12:80/scheduler", "filterVerb": "predicates/always_true", "prioritizeVerb": "priorities/zero_score", "preemptVerb": "preemption", "bindVerb": "", "weight": 1, "enableHttps": false, "nodeCacheCapable": false}],"hardPodAffinitySymmetricWeight" : 10}2、在my-kube-scheduler yaml文件中将configmaps:my-scheduler-config以文件的形式挂载到容器内/my-scheduler目录下,并在启动参数中指定--config=/my-scheduler/config.yaml,使用和默认调度器一样的镜像。 ...

April 30, 2019 · 1 min · jiezi

hadoopyarn内核资源隔离

整体:https://segmentfault.com/a/11...yarn是hadoop的资源隔离运行在YARN上带来的好处 : 一个集群部署多个版本计算资源按需伸缩不同负载应用混搭,集群利用率高共享底层存储,避免数据跨集群迁移 1.到RM申请,在一个Container中启动AM 包含异步的分配资源,暂存在缓冲区,等待AM来取2.AM RPC取资源并与NM通信 AM领取资源后分配任务不是yarn事情,用户自行实现3.包含各种状态同步,比如7,持续的nm到rm. 隔离算法目前只能实现cpu和内存的隔离1.可以占用空闲资源 Capacity Scheduler2.平均分配 Fair Scheduler基于cgroups linux/kernel/cgroup,包含子系统:cpu,io,mmemory,net等 内核中的代码在kennel下。用户使用:通过文件系统配置(内核给用户提供的方法)VFS 文件:ext2,ext3磁盘,socket,cgroups 。操作系统实现后可以通过mount挂载到cgroups文件系统vi /etc/cgconfig.conf。/sys/fs/cgroup/cpuset中配置即可对于内存并没有直接用cgroups内存隔离:线程监控进程内存量,不是超过立刻杀死,有个生命期 jvm不足以:每个任务不仅有java进程,reduce用C++不能单纯的cgroups内存树直接配置Linux中所有的进程都是通过fork()复制来实现的,而为了减少创建进程带来的堆栈消耗和性能影响,Linux使用了写时复制机制来快速创建进程。也就是说,一个子进程刚刚产生时,它的堆栈空间和父进程是完全一致的,那么从一开始它就拥有和父进程同样的ru_maxrss,如果父进程的ru_maxrss比较大,那么由于rusage计算值取最大值,就算在触发写时复制后,子进程使用的实际最大驻留集大小被更新,我们获得的也还是父进程的那个值,也就是说我们永远拿不到子进程真实使用的内存。Java创建子进程时采用了“fork() + exec()”的方案,子进程启动瞬间,它的内存使用量与父进程是一致的,exec系函数,这个系别的函数通过将当前进程的使用权转交给另一个程序,这时候进程原有的所有运行堆栈等数据将全部被销毁,因此ru_maxrss也会被清零计算,然后子进程的内存会恢复正常;也就是说,Container(子进程)的创建过程中可能会出现内存使用量超过预先定义的上限值的情况(取决于父进程,也就是NodeManager的内存使用量);此时,如果使用Cgroup进行内存资源隔离,这个Container就可能会被“kill”。虽然我们已经可以获得各个Container进程树的内存(物理内存、虚拟内存)使用量,但是我们不能仅凭进程树的内存使用量(物理内存、虚拟内存)是否超过上限值就决定是否“杀死”一个Container,因为“子进程”的内存使用量是有“波动”的,为了避免“误杀”的情况出现,Hadoop赋予每个进程“年龄”属性,并规定刚启动进程的年龄是1,MonitoringThread线程每更新一次,各个进程的年龄加一,在此基础上,选择被“杀死”的Container的标准如下:如果一个Contaier对应的进程树中所有进程(年龄大于0)总内存(物理内存或虚拟内存)使用量超过上限值的两倍;或者所有年龄大于1的进程总内存(物理内存或虚拟内存)使用量超过上限值,则认为该Container使用内存超量,可以被“杀死”。(注意:这里的Container泛指Container进程树)fork/exec/线程/进程在另一篇:xxk8s基本上完全基于cgroups。但是对于内存/磁盘这种没有就不行的不可压缩资源,会再加一个阈值,防止不稳定,能分配的会少于这个。所以k8s对于内存的限制会在fork时误放大没有处理。https://juejin.im/post/5b3d8c...

April 28, 2019 · 1 min · jiezi

基于-Docker-GogsJenkinsKubernetes-实践工程源代码的自动构建和持续集成与部署交付

本期目标 : 基于 Centos 7.6 , 封装出一个可用于运行 php 项目的开箱即用镜像本文不讨论 dockerfile 语法 , 并且假设你懂得基本的类unix 操作系统常识并拥有类unix 运行环境 (包括但不限于安装了mac 或 linux 的实体机 , 类unix虚拟机 , 安装了 MinGW 或 CygWin 的 windows 机器) , 并且认为你懂得基本的 docker 操作和有一定的 dockerfile 阅读能力准备工作建立工作目录 mkdir ~/docker-learncd ~/docker-learn创建Dockerfile touch Dockerfile然后拷贝你常用的 nginx.conf 到工作目录 cp xxx/nginx.conf nginx.conf封装基础镜像编辑我们创建好的 Dockerfile 基础内容声明本镜像继承自 centos 最新版 FROM centos安装 nginx创建nginx源文件 由于 centos 仓库里是没有 nginx 的 , 所以我们要自力更新添加nginx的源到 docker 里复制 nginx.org 里关于 RHEL 源的内容到 nginx.repo 文件也可以本地执行以下命令创建 nginx.repo ...

April 25, 2019 · 4 min · jiezi