Nginx简单的常规优化

配置nginx的work_process 查看当前服务的CPU核心数量 [root@containerd-master1 ~]# grep processor /proc/cpuinfo | wc -l 8 如果你需要修改更多的工作进程,请修改配置文件中的work_process字段 auto: 根据系统的CPU自动的设置工作进程数量 worker_processes 1; # 可选值 auto 配置work_connections 该参数表示每个工作进程最大处理的连接数,CentOS默认连接数为1024,连接数是可以修改的。 如果需要修改ulimit参数,请修改配置文件/etc/security/limits.conf noproc 是代表最大进程数 nofile 是代表最大文件打开数 本次修改仅仅以Rocky Linux和CentOS为例,不同的系统修改方法可能有所差异. * soft nofile 65535 * hard nofile 65535 配置nginx当中的work_connections events { worker_connections 65535; use epoll; } 简单的提一嘴ulimit的作用: 当进程打开的文件数目超过此限制时,该进程就会退出。 启用gzip压缩 nginx使用 gzip 进行文件压缩和解压缩,您可以节省带宽并在连接缓慢时提高网站的加载时间。 server { gzip on; # 开启gzip gzip_vary on; gzip_min_length 10240; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml; gzip_disable "MSIE [1-6]\."; } 限制nginx连接的超时 主要是为了减少打开和关闭连接时的处理器和网络开销 ...

三月 20, 2022 · 1 分钟 · iren.

什么是dockershim

先前了解 参考链接 Githubissue kubelet中的Docker支持现在已弃用,并将在未来的版本中删除。kubelet使用了一个名为dockershim的模块,该模块实现了对Docker的CRI支持,并在Kubernetes社区中发现了维护问题。我们鼓励您评估迁移到一个容器运行时的情况,该容器运行时是CRI(v1alpha1或v1兼容)的完整实现。 也就是说,在后续的Kubernetes1.20x版本以后会删除dockershim组件,但是由于目前Docker的使用用户众多,中间必然会有替换的一个过渡期,所以大家可以更多的关注一下其他的Container Runtime。 例如我们的Podman、Containerd、cri-o等其他容器运行时来运行kubernetes。 下面我们就具体来看看Kubernetes所提到的弃用dockershim到底是什么东西. CRI容器运行时接口 参考链接 CRI:容器运行时接口 container runtime interface,CRI 中定义了容器和镜像两个接口,实现了这两个接口目前主流的是:CRI-O、Containerd。(目前 PCI 产品使用的即为 Containerd)。 CRI接口的具体用处就在于 对容器操作的接口,包括容器的创建、启动和停止.即create、stop等操作。 对镜像的操作,下载、删除镜像等. 即pull、rmi等操作。 podsandbox OCI开放容器标准 OCI:开放容器标准 open container initiative,OCI 中定义了两个标准:容器运行时标准 和 容器镜像标准,实现了这一标准的主流是:runc(也即我们日常说的 Docker)、Kata-Container。 OCI的作用在于 ImageSpec(容器标准包) 文件系统:以 layer 保存的文件系统,每个 layer 保存了和上层之间变化的部分,layer 应该保存哪些文件,怎么表示增加、修改和删除的文件等 config 文件:保存了文件系统的层级信息(每个层级的 hash 值,以及历史信息),以及容器运行时需要的一些信息(比如环境变量、工作目录、命令参数、mount 列表),指定了镜像在某个特定平台和系统的配置。比较接近我们使用 docker inspect <image_id> 看到的内容 manifest 文件:镜像的 config 文件索引,有哪些 layer,额外的 annotation 信息,manifest 文件中保存了很多和当前平台有关的信息 index 文件:可选的文件,指向不同平台的 manifest 文件,这个文件能保证一个镜像可以跨平台使用,每个平台拥有不同的 manifest 文件,使用 index 作为索引 2.runtimeSpec: ociVersion(string, REQUIRED):是该州遵守的开放容器倡议运行时规范的版本。 id: 容器的 ID。这在此主机上的所有容器中必须是唯一的。不要求它在主机之间是唯一的。 status(string, REQUIRED): 加冕时容器的几个状态 1. creating 2. created 3. running 4. stopped pid: host上看到的容器进程 bundle:host上容器bundle目录的绝对路径 annotation:容器相关的标注,可选 所以在Json的序列化时,必须遵守以下格式 ...

二月 13, 2022 · 1 分钟 · iren.

有关于Kubernetes中影响Pod调度的问题

此问题引出的是生产环境中所有的资源完全充足,但是会出现更新Pod、删除Pod、新建Pod无法调度的情况。 生产环境解决问题办法 找到问题跟原所在,默认的maxPods: 110,K8S默认一个节点上的pod调度数是110,当前有限制pod数的需求。 vim /var/lib/kubelet/config.yaml maxPods: 110 # 修改为maxPods: 330 影响Pod调度的情况 requests资源限制 requests:是一种硬限制,Kubernetes在进行Pod请求调度的时候,节点的可用资源必须满足500m的CPU才能进行调度,且使用最大限制为1个CPU,如果该Pod超过请求的最大限制,则Kubernetes将会把该Pod进行Kill重启。 resources: limits: cpu: '1' requests: cpu: 500m 当你设置request为500m以及limit为1000m的时候,当你使用 kubectl describe node查看节点资源的时候可能会与你设置的请求量不符合,这是以你Pod 的实际使用量为标准的。 节点标签的Label 标签选择器: kubectl label node kubernetes-node1 env_role=dev 通过此命令对相应的节点加入标签 kubectl label node 节点名称 标签名称 spec: nodeSelector: env_role: dev 当然,你也可以通过kubectl get node --show-labels命令查看当前节点的标签 NAME STATUS ROLES AGE VERSION LABELS master1 Ready,SchedulingDisabled master 141d v1.17.9 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master1,kubernetes.io/os=linux,node-role.kubernetes.io/master= master2 Ready,SchedulingDisabled master 139d v1.17.9 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master2,kubernetes.io/os=linux,node-role.kubernetes.io/master= master3 Ready,SchedulingDisabled master 139d v1.17.9 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master3,kubernetes.io/os=linux,node-role.kubernetes.io/master= node1 Ready worker 141d v1.17.9 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node1,kubernetes.io/os=linux,node-role.kubernetes.io/worker= node2 Ready worker 141d v1.17.9 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node2,kubernetes.io/os=linux,node-role.kubernetes.io/worker= node3 Ready worker 141d v1.17.9 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node3,kubernetes.io/os=linux,node-role.kubernetes.io/worker= 节点亲和性 节点亲和性:nodeAffinity和之前nodeSelector基本上是一样的,有的话满足进行调度,如果没有的话则依旧也可以调度。 硬亲和性:requiredDuringSchedulingIgnoreDuringExecution,当前约束的条件表示为在env_role这个键中有dev/test 有的话即满足的调度,如果不满足则不调度。 软亲和性: preferredDuringSchedulingIgnoredDuringExecution,进行尝试是否满足测试,如果满足则满足调度,如果不满足则依旧会进行调度。 支持的操作符:In/Not In/Gt/Lt/DoesNotExists分别为 存在、不存在、大于、小于、不存在。 spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoreDuringExecution: nodeSelectorTerms: - metchExpressions: - key: env_role operator: In values: - dev - test preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 # 表示权重 比例 preference: matchExpressions: - key: group operator: In # 操作符 In values: - otherprod 污点和污点容忍 污点:nodeSelector和nodeAffinityPod调度在某些节点上,是属于Pod的属性,在调度的时候进行实现,而污点是对节点做不分配调度,是节点属性。 污点容忍:当一个污点不允许被调度的时候,同时又想让他可能会参与调度,类似于软亲和性。 场景:作为专用节点、配置特定硬件节点、基于Taint驱逐 NoSchedule:一定不被调度 PreferNoSchdule: 尽量不被调度 NoExecute: 不调度,并且会驱逐在该节点上Pod # 污点容忍 spec: tolerations: - key: "env_role" operator: "Equal" value: "yes" effect: "NoSchedule" 使用kubectl describe node kubernetes-master1 | grep Taints进行查看是否为污点。 使用kubectl taint node 节点名称 key=value:污点值 ...

十二月 21, 2021 · 1 分钟 · iren.

kubernetes-离线部署Skywallking

注意:请各位记住把所有离线包全拿到本地… 在线部署chartmuseum 直接使用最简单的 docker run 方式,使用local 本地存储方式,通过 -v 映射到宿主机 /opt/charts 更多支持安装方式见官网 mkdir /opt/charts docker run -d \ -p 8080:8080 \ -e DEBUG=1 \ -e STORAGE=local \ -e STORAGE_LOCAL_ROOTDIR=/charts \ -v /opt/charts:/charts \ chartmuseum/chartmuseum:latest 下载Skywalking包 git clone https://github.com/apache/skywalking-kubernetes.git # 更换仓库 cd skywalking-kubernetes-master/chart/skywalking/ vim Chats.yaml dependencies: - name: elasticsearch version: ~7.12.1 # 官网的版本号为7.5.1 最新的elastic版本为7.12.1 repository: http://localhost:8080 # 修改为你本地的Repo地址 condition: elasticsearch.enabled 添加elasticsearch仓库 helm repo add elastic https://helm.elastic.co helm pull elastic/elasticsearch # 把elasticsearch内容拉下来 上传本地Helm 以防万一请先安装helmpush插件 ...

四月 7, 2021 · 3 分钟 · iren.

Redis集群搭建

Redis Cluster(Redis集群)简介 redis是一个开源的key value存储系统,受到了广大互联网公司的青睐。redis3.0版本之前只支持单例模式,在3.0版本及以后才支持集群,我这里用的是redis3.0.0版本; redis集群采用P2P模式,是完全去中心化的,不存在中心节点或者代理节点; redis集群是没有统一的入口的,客户端(client)连接集群的时候连接集群中的任意节点(node)即可,集群内部的节点是相互通信的(PING-PONG机制),每个节点都是一个redis实例; 为了实现集群的高可用,即判断节点是否健康(能否正常使用),redis-cluster有这么一个投票容错机制:如果集群中超过半数的节点投票认为某个节点挂了,那么这个节点就挂了(fail)。这是判断节点是否挂了的方法; 那么如何判断集群是否挂了呢? -> 如果集群中任意一个节点挂了,而且该节点没有从节点(备份节点),那么这个集群就挂了。这是判断集群是否挂了的方法; 那么为什么任意一个节点挂了(没有从节点)这个集群就挂了呢? -> 因为集群内置了16384个slot(哈希槽),并且把所有的物理节点映射到了这16384[0-16383]个slot上,或者说把这些slot均等的分配给了各个节点。当需要在Redis集群存放一个数据(key-value)时,redis会先对这个key进行crc16算法,然后得到一个结果。再把这个结果对16384进行求余,这个余数会对应[0-16383]其中一个槽,进而决定key-value存储到哪个节点中。所以一旦某个节点挂了,该节点对应的slot就无法使用,那么就会导致集群无法正常工作。 综上所述,每个Redis集群理论上最多可以有16384个节点。 Redis集群至少需要3个节点,因为投票容错机制要求超过半数节点认为某个节点挂了该节点才是挂了,所以2个节点无法构成集群。 要保证集群的高可用,需要每个节点都有从节点,也就是备份节点,所以Redis集群至少需要6台服务器。因为我没有那么多服务器,也启动不了那么多虚拟机,所在这里搭建的是伪分布式集群,即一台服务器虚拟运行6个redis实例,修改端口号为(7001-7006)1+1+1+1+1+1 = 6 搭建集群 Redis版本6.0.8 Gcc7x.x.x 创建目录 mkdir /usr/local/redis-cluster cd /usr/local/redis-cluster wget http://download.redis.io/releases/redis-6.0.8.tar.gz mkdir {7001..7006} 复制配置文件 tar -zxf redis-6.0.8.tar.gz cd redis-6.0.8/ && make install cp -a redis-6.0.8/redis.conf 7001/ # 以此类推 cp -a redis-6.0.8/redis.conf 7002/ 如果你不想编译安装的话,你可以把redis中的/bin目录的命令移动到每个node节点文件夹中,这样以方便你使用redis-server命令 编辑配置文件 此文件内容为集群模式最小配置文件内容. vim 7001/redis.conf # 以此类推,记得更改端口号和日志文件 bind 127.0.0.1 # IP可更换为内网IP port 7001 cluster-enabled yes cluster-config-file nodes7001.conf cluster-node-timeout 5000 appendonly yes daemonize yes logfile /usr/local/redis-cluster/7001/redis-7001.log maxmemory 4GB requirepass ******* dir /usr/local/redis-cluster/7001 masterauth **** port 7001 Redis运行端口 cluster-enabled yes启用集群模式 cluster-config-file nodes.conf集群模式配置文件 cluster-node-timeout 5000节点的超时时限 appendonly yes开启AOF持久化 daemonize yes开启后台运行 maxmemory 4GBRedis最大可用内存 requirepass连接Redis客户端密码 masterauth Slave连接master需要的认证 启动集群 自己建一个启动脚本,要不然手动启动太麻烦了 ...

二月 19, 2021 · 2 分钟 · iren.

kubernetes-Service解读

Service的简单理解 Service 是一种抽象的对象,它定义了一组 Pod 的逻辑集合和一个用于访问它们的策略,其实这个概念和微服务非常类似。一个 Serivce 下面包含的 Pod 集合是由 Label Selector 来决定的。 假如我们后端运行了3个副本,这些副本都是可以替代的,因为前端并不关心它们使用的是哪一个后端服务。尽管由于各种原因后端的 Pod 集合会发送变化,但是前端却不需要知道这些变化,也不需要自己用一个列表来记录这些后端的服务,Service 的这种抽象就可以帮我们达到这种解耦的目的。 三种IP 在继续往下学习 Service 之前,我们需要先弄明白 Kubernetes 系统中的三种IP,因为经常有同学混乱。 NodeIP:Node 节点的 IP 地址 PodIP: Pod 的 IP 地址 ClusterIP: Service 的 IP 地址 首先,NodeIP是Kubernetes集群中节点的物理网卡IP地址(一般为内网),所有属于这个网络的服务器之间都可以直接通信,所以Kubernetes集群外要想访问Kubernetes集群内部的某个节点或者服务,肯定得通过Node P进行通信(这个时候一般是通过外网 IP 了) 然后PodIP是每个Pod的IP地址,它是网络插件进行分配的,前面我们已经讲解过 最后ClusterIP是一个虚拟的IP,仅仅作用于Kubernetes Service 这个对象,由Kubernetes自己来进行管理和分配地址。 定义Servcie 定义 Service 的方式和我们前面定义的各种资源对象的方式类型,例如,假定我们有一组 Pod 服务,它们对外暴露了 8080 端口,同时都被打上了 app=beijing-nginx 这样的标签,那么我们就可以像下面这样来定义一个 Service 对象 apiVersion: v1 kind: Service metadata: name: public-beijing-nginx-service spec: selector: app: beijing-nginx ports: - protocol: TCP port: 80 targetPort: 80 # 可以理解成是service的访问端口 name: beijing-nginx-http 然后通过的使用 kubectl create -f myservice.yaml 就可以创建一个名为 myservice 的 Service 对象,它会将请求代理到使用 TCP 端口为 80,具有标签 app=beijing-nginx-http 的 Pod 上,这个 Service 会被系统分配一个我们上面说的 Cluster IP,该 Service 还会持续的监听 selector 下面的 Pod,会把这些 Pod 信息更新到一个名为 myservice 的Endpoints 对象上去,这个对象就类似于我们上面说的 Pod 集合了。 ...

四月 13, 2020 · 5 分钟 · iren.

基于kubernetes部署nacos集群

简单安装使用 最新版本应该是1.4.1 git clone https://github.com/nacos-group/nacos-k8s.git 简单使用 如果你使用简单方式快速启动,请注意这是没有使用持久化卷的,可能存在数据丢失风险:!!! cd nacos-k8s chmod +x quick-startup.sh ./quick-startup.sh 演示使用 服务注册 curl -X PUT 'http://cluster-ip:8848/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080' 服务发现 curl -X GET 'http://cluster-ip:8848/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName' 发布配置 curl -X POST "http://cluster-ip:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=helloWorld" 获取配置 curl -X GET "http://cluster-ip:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test" 高级用法 在高级使用中,Nacos在K8S拥有自动扩容缩容和数据持久特性,请注意如果需要使用这部分功能请使用PVC持久卷,Nacos的自动扩容缩容需要依赖持久卷,以及数据持久化也是一样,本例中使用的是NFS来使用PVC. 部署NFS nfs-client-provisioner 可动态为kubernetes提供pv卷,是Kubernetes的简易NFS的外部provisioner,本身不提供NFS,需要现有的NFS服务器提供存储。持久卷目录的命名规则为: ${namespace}-${pvcName}-${pvName} 创建角色 kubectl create -f deploy/nfs/rbac.yaml 修改NFS的yaml vim nacos-k8s/deploy/nfs/deployment.yaml apiVersion: v1 kind: ServiceAccount metadata: name: nfs-client-provisioner --- kind: Deployment apiVersion: apps/v1 metadata: name: nfs-client-provisioner spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: nfs-client-provisioner template: metadata: labels: app: nfs-client-provisioner spec: serviceAccount: nfs-client-provisioner containers: - name: nfs-client-provisioner image: quay.io/external_storage/nfs-client-provisioner:latest volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: fuseim.pri/ifs - name: NFS_SERVER value: 10.1.6.93 # 修改NFS的IP为你本地的NFSIP地址 - name: NFS_PATH value: /server/nacos volumes: - name: nfs-client-root nfs: server: 10.1.6.93 # 同上 path: /server/nacos 部署NFS-client ...

四月 7, 2020 · 1 分钟 · iren.

kubernetes-Scheduler简单详解

kube-scheduler 是 kubernetes 的核心组件之一,主要负责整个集群资源的调度功能,根据特定的调度算法和策略,将 Pod 调度到最优的工作节点上面去,从而更加合理、更加充分的利用集群的资源,这也是我们选择使用 kubernetes 一个非常重要的理由。如果一门新的技术不能帮助企业节约成本、提供效率,我相信是很难推进的。 调度流程 kube-scheduler 提供的默认调度器能够满足我们绝大多数的要求,我们前面和大家接触的示例也基本上用的默认的策略,都可以保证我们的 Pod 可以被分配到资源充足的节点上运行。但是在实际的线上项目中,可能我们自己会比 kubernetes 更加了解我们自己的应用,比如我们希望一个 Pod 只能运行在特定的几个节点上,或者这几个节点只能用来运行特定类型的应用,这就需要我们的调度器能够可控。 发起创建Deployment请求->API Server,这个时候APIServer会进行一系列的逻辑处理,例如: 鉴权、查看你是否有权限操作、Deployment创建是否合法等等,然后将请求存储到etcd当中并且转发给Controller Manager Controller Manager会监听API Server,这个时候假设监听到的是一个创建Deployment的请求,则会把请求转发到Deployment Controller Deployment Controller接受到请求后创建ReplicaSet,然后ReplicaSet Controller会根据yaml当中定义的template模板来进行创建Pod,然后返回给API Server 在创建之初的Pod属性中nodeName为空,也就是没有被调度过的,这个时候调度器就会对它进行调度,调度去watchPod对象,然后分析那个节点最适合这个Pod,然后将节点的名字通过类似于bind的这种方法写入到nodeName当中。 然后该节点的kubelet会进行一系列的判断,然后进入Create Pod的流程,然后进行一系列的CNI和CSI的过程。 这也就是我们常说的往往越简单的东西,背后实现的越复杂。 调度阶段 kube-scheduler调度分为两个阶段 predicate: 过滤阶段,过滤不符合条件的节点。 priority: 优先级排序,选择优先级最高的节点,也就是给节点打分。 Predicates策略 PodFitsHostPorts: 检查是否有Host Ports冲突 PodFitsPorts: 同上 PodFitsResources: 检查Node的资源是否充足,包括允许的Pod数量、CPU、内存、GPU个数以及其他的OpaqueIntResources。 HostName:检查pod.Spec.NodeName是否与候选节点一致 MatchNodeSelector:检查候选节点的pod.Spec.NodeSelector是否匹配 NoVolumeZoneConflict:检查volume zone是否冲突 Priority策略 SelectorSpreadPriority: 优先减少节点上属于同一个Service或Replication Controller的Pod数量。 InterPodAffinityPriority: 优先将Pod调度到相同的拓扑上 LeastRequestedPriority:优先调度到请求资源少的节点上 BalancedResourceAllocation: 优先平衡各节点的资源使用 NodePreferAvoidPodsPriority:权重判断 太多了可以自己去官网了解一下,这些策略都可以通过scheduler配置文件去配置,其实一般来说我们不太需要,我觉得kubernetes的调度是最让我们省心的。 资源需求 requests:属于调度器调度的时候所参考的指标,也就是说我这个应用最少需要250m的cpu和256m的内存才能运行。 kind: Deployment apiVersion: apps/v1 metadata: name: nginx-deployment namespace: default labels: app: nginx version: qa spec: replicas: 2 selector: matchLabels: app: nginx version: qa template: metadata: creationTimestamp: null labels: app: nginx version: qa spec: volumes: - name: host-time hostPath: path: /etc/localtime type: '' containers: - name: nginx image: nginx:latest ports: - name: http-web containerPort: 80 protocol: TCP resources: limits: cpu: '1' memory: 2Gi requests: cpu: 250m memory: 256Mi 可以查看你节点的一些资源状态 ...

三月 14, 2020 · 2 分钟 · iren.