務實之選 二十來萬的合資SUV有啥好選擇?

標緻4008的內飾採用了飛航式設計理念,飛機推桿式的檔把和撥片式的功能鍵顯得頗為新穎,小尺寸方向盤給人以一種很強烈的戰鬥氣息。350THp車型搭載的是一台1。6T渦輪增壓發動機,最大馬力167匹,峰值扭矩245牛米,傳動系統也是一款6AT手自一體變速箱。

做汽車編輯久了,總會碰到很多朋友問同一個問題,就是預算二十來萬,買一台合資SUV有啥好的車型?往往這個問題後面會帶上一句:不買日系車。

在這個預算區間現在可以購買的合資SUV已經非常非常多,這次就根據小編個人所開過和感受過車型做一個推薦,前提是,今兒不說日系。

操控至上—福特翼虎

指導價格:19.38-27.58萬

推薦車型:EcoBoost 180 兩驅豪翼型

指導價格:22.98萬

福特翼虎在更換了家族式盾型前臉之後確實顯得更加漂亮了,大嘴式的進氣格柵讓它有了更加威武的視覺效果,車身線條方正,車尾的銀色下護板和雙邊排氣管也體現出了一種運動氛圍。

翼虎的內飾呈現環抱式設計,駕駛感受更接近一台轎車,而且有着良好的開車視野,車內座椅填充柔軟度適中,乘坐人員也不會顯得難受膈應。

EcoBoost 180搭載的是一台1.5T的渦輪增壓發動機,最大馬力181匹,峰值扭矩240牛米,傳動系統使用的是福特自家的6AT手自一體變速箱。

福特翼虎是二十萬級別裏面操控性能和運動感較好的一台SUV,轉向精準,動力儲備也很足,雖然1.5T的發動機在低扭時候感覺那麼一點拖沓,但是由於福特一貫將油門初段調校得較為敏感的特性,所以起步感覺並不會顯得太肉;而2000轉的時候會迎來扭矩爆發,加速超車稍微給油,翼虎的動力響應還是可以讓人滿意的類型。

個性為先—標緻4008

指導價格:18.57-23.37萬

推薦車型:2017款 350THp豪華版

指導價格:23.07萬

標緻4008的外觀設計秉承了法系車天馬行空的創意,但卻比以往的標緻品牌車型要來的更加和諧,車身肌肉感很強烈,給人以一種比較明顯的力量感,不同於普通SUV使用相對方正的設計理念,標緻4008的外觀顯得流線型更加強烈,視覺效果更加時尚。

標緻4008的內飾採用了飛航式設計理念,飛機推桿式的檔把和撥片式的功能鍵顯得頗為新穎,小尺寸方向盤給人以一種很強烈的戰鬥氣息。

350THp車型搭載的是一台1.6T渦輪增壓發動機,最大馬力167匹,峰值扭矩245牛米,傳動系統也是一款6AT手自一體變速箱。

標緻4008從外觀上說是一款非常個性前衛的SUV;標緻車型以往給人的感覺似乎一直與操控感和運動格調相關聯,但本次的標緻4008則更趨向於一台普羅大眾所理解的歐系SUV,底盤和懸挂調校偏向舒適,但扭矩爆發平台會來得比福特翼虎更早,1400轉就可以達到峰值扭矩,所以超車感覺還是相當暢快。

均衡主義—現代途勝

指導價格:15.99-23.99萬

推薦車型:2015款 1.6T 雙離合四驅尊貴型

指導價格:21.59萬

途勝的外觀設計延續了現代集團的設計理念,細節之處還是比較個性的類型,但整體看上去比較中庸,從外觀上就給人一種比較溫柔的親和力形象。

內飾的設計也是走的柔和路線,類似展翼的設計語言看上去比較溫馨,加之韓系車型血統,人機工程學的設計布局也十分符合我們中國消費者的使用習慣,溝通感比較優秀。

動力層面途勝使用的1.6T發動機最大馬力177匹,峰值扭矩265牛米,傳動系統使用的是一套7速雙離合變速箱。

途勝的性格是一款比較溫順好用的家用SUV,1.6T的動力平台也比較早,1500轉就可以輸出最大扭矩,雙離合變速箱也比較平順好用。車內布局也是非常舒適,從家用層面來說著實是一款不錯的SUV。

全文總結:以上三款車,從家用務實的角度來看小編推薦的是現代途勝,韓系SUV一直都以比較舒適、平和的性格在市場上立足,而且定價不高,21萬出頭的價格可以購買四驅版本,這是歐美系同級別SUV難以企及的配置,有四驅,在泥濘爛路的信心也更加充足。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

網頁設計最專業,超強功能平台可客製化

※別再煩惱如何寫文案,掌握八大原則!

最新研究:大氣二氧化碳總量逼近1500萬年來高峰

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

※別再煩惱如何寫文案,掌握八大原則!

海洋最大謎團——沒人看過鯨鯊生小孩 科學家取得腹部超音波仍無果

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

網頁設計最專業,超強功能平台可客製化

※別再煩惱如何寫文案,掌握八大原則!

業界也認了 不是所有生質能都是碳中性 歐盟面臨減碳新挑戰

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

伊朗火災與爆炸頻傳 伊斯法罕省電廠也傳事故

摘錄自2020年7月19日中央社報導

伊朗中部伊斯法罕省一座電廠今天(19日)發生爆炸。所幸沒有人員傷亡。電廠過了約兩小時恢復正常運作,伊斯法罕省供電不受影響。

伊朗各地的軍事與民用設施近幾週頻傳火災與爆炸事故,讓伊朗境內人士懷疑可能是宿敵以色列在搞破壞。以色列指控伊朗試圖發展核彈,伊朗則堅稱本身的核子計畫完全是為了和平目的。

首都德黑蘭(Tehran)6月下旬就發生兩起爆炸,其中一起發生在軍事用地附近,另一起衛生中心的火災則奪走19人性命。本月稍早,伊朗南部一座造船廠、德黑蘭南方一座工廠,以及伊朗中部的納坦茲(Natanz)核設施,也分別發生火災或爆炸事故。其中工廠事故奪走兩人性命。伊朗當局形容納坦茲核設施起火是意外,他們基於「安全理由」不公布事發原因及細節。

土地利用
能源轉型
國際新聞
伊朗
火力發電廠
火災
災害
核能

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

在k8s上部署日誌系統elfk

日誌系統elfk

前言

經過上周的技術預研,在本周一通過開會研究,根據公司的現有業務流量和技術棧,決定選擇的日誌系統方案為:elasticsearch(es)+logstash(lo)+filebeat(fi)+kibana(ki)組合。es選擇使用aliyun提供的es,lo&fi選擇自己部署,ki是阿里雲送的。因為申請ecs需要一定的時間,暫時選擇部署在測試&生產環境(吐槽一下,我司測試和生產公用一套k8s並且託管與aliyun……)。用時一天(前期有部署的差不多過)完成在kubernetes上部署完成elfk(先部署起來再說,優化什麼的後期根據需要再搞)。

組件簡介

es 是一個實時的、分佈式的可擴展的搜索引擎,允許進行全文、結構化搜索,它通常用於索引和搜索大量日誌數據,也可用於搜索許多不同類型的文。

lo 主要的有點就是它的靈活性,主要因為它有很多插件,詳細的文檔以及直白的配置格式讓它可以在多種場景下應用。我們基本上可以在網上找到很多資源,幾乎可以處理任何問題。

作為 Beats 家族的一員,fi 是一個輕量級的日誌傳輸工具,它的存在正彌補了 lo 的缺點fi作為一個輕量級的日誌傳輸工具可以將日誌推送到中心lo。

ki是一個分析和可視化平台,它可以瀏覽、可視化存儲在es集群上排名靠前的日誌數據,並構建儀錶盤。ki結合es操作簡單集成了絕大多數es的API,是專業的日誌展示應用。

數據採集流程圖

日誌流向:logs_data—> fi —> lo —> es—> ki。

logs_data通過fi收集日誌,輸出到lo,通過lo做一些過濾和修改之後傳送到es數據庫,ki讀取es數據庫做分析。

部署

根據我司的實際集群狀況,此文檔部署將完全還原日誌系統的部署情況。

在本地MAC安裝kubectl連接aliyun託管k8s

在客戶端(隨便本地一台虛機上)安裝和託管的k8s一樣版本的kubectl

curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.14.8/bin/linux/amd64/kubectl   
chmod +x ./kubectl 
mv ./kubectl /usr/local/bin/kubectl  
將阿里雲託管的k8s的kubeconfig 複製到$HOME/.kube/config 目錄下,注意用戶權限的問題
部署ELFK

申請一個名稱空間(一般一個項目一個名稱空間)。

# cat kube-logging.yaml 
apiVersion: v1
kind: Namespace
metadata:
  name: loging

部署es。網上找個差不多的資源清單,根據自己的需求進行適當的修改,運行,出錯就根據日誌進行再修改。

# cat elasticsearch.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-class
  namespace: loging
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
# Supported policies: Delete, Retain
reclaimPolicy: Delete
---
kind: PersistentVolume
apiVersion: v1
metadata:
  name: datadir1
  namespace: logging
  labels:
    type: local
spec:
  storageClassName: local-class
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/data/data1"
--- 
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: elasticsearch
  namespace: loging
spec:
  serviceName: elasticsearch
  selector:
    matchLabels:
      app: elasticsearch
  template:
    metadata:
      labels:
        app: elasticsearch
    spec:
      containers:
      - name: elasticsearch
        image: elasticsearch:7.3.1
        resources:
            limits:
              cpu: 1000m
            requests:
              cpu: 100m
        ports:
        - containerPort: 9200
          name: rest
          protocol: TCP
        - containerPort: 9300
          name: inter-node
          protocol: TCP
        volumeMounts:
        - name: data
          mountPath: /usr/share/elasticsearch/data
        env:
          - name: "discovery.type"
            value: "single-node"
          - name: cluster.name
            value: k8s-logs
          - name: node.name
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: ES_JAVA_OPTS
            value: "-Xms512m -Xmx512m"
      initContainers:
      - name: fix-permissions
        image: busybox
        command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"]
        securityContext:
          privileged: true
        volumeMounts:
        - name: data
          mountPath: /usr/share/elasticsearch/data
      - name: increase-vm-max-map
        image: busybox
        command: ["sysctl", "-w", "vm.max_map_count=262144"]
        securityContext:
          privileged: true
      - name: increase-fd-ulimit
        image: busybox
        command: ["sh", "-c", "ulimit -n 65536"]
        securityContext:
          privileged: true
  volumeClaimTemplates:
  - metadata:
      name: data
      labels:
        app: elasticsearch
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "local-class"
      resources:
        requests:
          storage: 5Gi
---
kind: Service
apiVersion: v1
metadata:
  name: elasticsearch
  namespace: loging
  labels:
    app: elasticsearch
spec:
  selector:
    app: elasticsearch
  clusterIP: None
  ports:
    - port: 9200
      name: rest
    - port: 9300
      name: inter-node

部署ki。因為根據數據採集流程圖,ki是和es結合的,配置相對簡單。

# cat kibana.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: kibana
  namespace: loging
  labels:
    k8s-app: kibana
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: kibana
  template:
    metadata:
      labels:
        k8s-app: kibana
    spec:
      containers:
      - name: kibana
        image: kibana:7.3.1
        resources:
          limits:
            cpu: 1
            memory: 500Mi
          requests:
            cpu: 0.5
            memory: 200Mi
        env:
          - name: ELASTICSEARCH_HOSTS
#注意value是es的services,因為es是有狀態,用的無頭服務,所以連接的就不僅僅是pod的名字了
            value: http://elasticsearch:9200   
        ports:
        - containerPort: 5601
          name: ui
          protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: kibana
  namespace: loging
spec:
  ports:
  - port: 5601
    protocol: TCP
    targetPort: ui
  selector:
    k8s-app: kibana

配置ingress-controller。因為我司用的是阿里雲託管的k8s自帶的nginx-ingress,並且配置了強制轉換https。所以kibana-ingress也要配成https。

# openssl genrsa -out tls.key 2048
# openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=kibana.test.realibox.com
# kubectl create secret tls kibana-ingress-secret --cert=tls.crt --key=tls.key

kibana-ingress配置如下。提供兩種,一種是https,一種是http。

https:
# cat kibana-ingress.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kibana
  namespace: loging
spec:
  tls:
  - hosts:
    - kibana.test.realibox.com
    secretName: kibana-ingress-secret
  rules:
  - host: kibana.test.realibox.com
    http:
      paths:
      - path: /
        backend:
          serviceName: kibana
          servicePort: 5601

http:
# cat kibana-ingress.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kibana
  namespace: loging
spec:
  rules:
  - host: kibana.test.realibox.com
    http:
      paths:
      - path: /
        backend:
          serviceName: kibana
          servicePort: 5601

部署lo。因為lo的作用是對fi收集到的日誌進行過濾,需要根據不同的日誌做不同的處理,所以可能要經常性的進行改動,要進行解耦。所以選擇以configmap的形式進行掛載。

# cat logstash.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: logstash
  namespace: loging
spec:
  replicas: 1
  selector:
    matchLabels:
      app: logstash
  template:
    metadata:
      labels:
        app: logstash
    spec:
      containers:
      - name: logstash
        image: elastic/logstash:7.3.1
        volumeMounts:
        - name: config
          mountPath: /opt/logstash/config/containers.conf
          subPath: containers.conf
        command:
        - "/bin/sh"
        - "-c"
        - "/opt/logstash/bin/logstash -f /opt/logstash/config/containers.conf"
      volumes:
      - name: config
        configMap:
          name: logstash-k8s-config
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: logstash
  name: logstash
  namespace: loging
spec:
  ports:
    - port: 8080       
      targetPort: 8080
  selector:
    app: logstash
  type: ClusterIP

# cat logstash-config.yaml 
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: logstash
  name: logstash
  namespace: loging
spec:
  ports:
    - port: 8080       
      targetPort: 8080
  selector:
    app: logstash
  type: ClusterIP
---

apiVersion: v1
kind: ConfigMap
metadata:
  name: logstash-k8s-config
  namespace: loging
data:
  containers.conf: |
    input {
      beats {
        port => 8080  #filebeat連接端口
      }
    }
    output {
      elasticsearch {
        hosts => ["elasticsearch:9200"]  #es的service
        index => "logstash-%{+YYYY.MM.dd}"
      }
    }
注意:修改configmap 相當於修改鏡像。必須重新apply 應用資源清單才能生效。根據數據採集流程圖,lo的數據由fi流入,流向es。

部署fi。fi的主要作用是進行日誌的採集,然後將數據交給lo。

# cat filebeat.yaml 
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-config
  namespace: loging
  labels:
    app: filebeat
data:
  filebeat.yml: |-
    filebeat.config:
      inputs:
        # Mounted `filebeat-inputs` configmap:
        path: ${path.config}/inputs.d/*.yml
        # Reload inputs configs as they change:
        reload.enabled: false
      modules:
        path: ${path.config}/modules.d/*.yml
        # Reload module configs as they change:
        reload.enabled: false
    # To enable hints based autodiscover, remove `filebeat.config.inputs` configuration and uncomment this:
    #filebeat.autodiscover:
    #  providers:
    #    - type: kubernetes
    #      hints.enabled: true
    output.logstash:
      hosts: ['${LOGSTASH_HOST:logstash}:${LOGSTASH_PORT:8080}']   #流向lo
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-inputs
  namespace: loging
  labels:
    app: filebeat
data:
  kubernetes.yml: |-
    - type: docker
      containers.ids:
      - "*"
      processors:
        - add_kubernetes_metadata:
            in_cluster: true
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: filebeat
  namespace: loging
  labels:
    app: filebeat
spec:
  selector:
    matchLabels:
      app: filebeat
  template:
    metadata:
      labels:
        app: filebeat
    spec:
      serviceAccountName: filebeat
      terminationGracePeriodSeconds: 30
      containers:
      - name: filebeat
        image: elastic/filebeat:7.3.1
        args: [
          "-c", "/etc/filebeat.yml",
          "-e",
        ]
        env:   #注入變量
        - name: LOGSTASH_HOST
          value: logstash
        - name: LOGSTASH_PORT
          value: "8080"
        securityContext:
          runAsUser: 0
          # If using Red Hat OpenShift uncomment this:
          #privileged: true
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 100Mi
        volumeMounts:
        - name: config
          mountPath: /etc/filebeat.yml
          readOnly: true
          subPath: filebeat.yml
        - name: inputs
          mountPath: /usr/share/filebeat/inputs.d
          readOnly: true
        - name: data
          mountPath: /usr/share/filebeat/data
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      volumes:
      - name: config
        configMap:
          defaultMode: 0600
          name: filebeat-config
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers
      - name: inputs
        configMap:
          defaultMode: 0600
          name: filebeat-inputs
      # data folder stores a registry of read status for all files, so we don't send everything again on a Filebeat pod restart
      - name: data
        hostPath:
          path: /var/lib/filebeat-data
          type: DirectoryOrCreate
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: filebeat
subjects:
- kind: ServiceAccount
  name: filebeat
  namespace: loging
roleRef:
  kind: ClusterRole
  name: filebeat
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: filebeat
  labels:
    app: filebeat
rules:
- apiGroups: [""] # "" indicates the core API group
  resources:
  - namespaces
  - pods
  verbs:
  - get
  - watch
  - list
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: filebeat
  namespace: loging
  labels:
    app: filebeat
---

至此完成在k8s上部署es+lo+fi+ki ,進行簡單驗證。

驗證

查看svc、pod、ingress信息

# kubectl get svc,pods,ingress -n loging
NAME                    TYPE        CLUSTER-IP        EXTERNAL-IP   PORT(S)             AGE
service/elasticsearch   ClusterIP   None              <none>        9200/TCP,9300/TCP   151m
service/kibana          ClusterIP   xxx.168.239.2xx   <none>        5601/TCP            20h
service/logstash        ClusterIP   xxx.168.38.1xx   <none>        8080/TCP            122m

NAME                            READY   STATUS    RESTARTS   AGE
pod/elasticsearch-0             1/1     Running   0          151m
pod/filebeat-24zl7              1/1     Running   0          118m
pod/filebeat-4w7b6              1/1     Running   0          118m
pod/filebeat-m5kv4              1/1     Running   0          118m
pod/filebeat-t6x4t              1/1     Running   0          118m
pod/kibana-689f4bd647-7jrqd     1/1     Running   0          20h
pod/logstash-76bc9b5f95-qtngp   1/1     Running   0          122m

NAME                        HOSTS                       ADDRESS        PORTS     AGE
ingress.extensions/kibana   kibana.test.realibox.com   xxx.xx.xx.xxx   80, 443   19h
web配置

配置索引

發現

至此算是簡單完成。後續需要不斷優化,不過那是後事了。

問題總結

這應該算是第一次親自在測試&生產環境部署應用了,而且是自己很不熟悉的日子系統,遇到了很多問題,需要總結。

  1. 如何調研一項技術棧;
  2. 如何選定方案;
  3. 因為網上幾乎沒有找到類似的方案(也不曉得別的公司是怎麼搞的,反正網上找不到有效的可能借鑒的)。需要自己根據不同的文檔總結嘗試;
  4. 一個組件的標籤盡可能一致;
  5. 如何查看公司是否做了端口限制和https強制轉換;
  6. 遇到IT的事一定要看日誌,這點很重要,日誌可以解決絕大多數問題;
  7. 一個人再怎麼整也會忽略一些點,自己先嘗試然後請教朋友,共同進步。
  8. 項目先上線再說別的,目前是這樣,一件事又百分之20的把握就可以去做了。百分之80再去做就沒啥意思了。
  9. 自學重點學的是理論,公司才能學到操作。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※推薦評價好的iphone維修中心

簡單5步,輕鬆debug K8S服務!

作者:
Ram Rai,性能、可擴展性以及軟件架構的愛好者

原文鏈接:
https://medium.com/better-programming/debug-your-kubernetes-service-in-5-easy-steps-1457974f024c

在Kubernetes中,服務是一個核心概念。在本文中,將介紹如何調試K8S服務,這些服務是由多個Pod組成的工作負載的抽象接口(主機+端口)。

在我們深入探索debug方法之前,我們先簡單回顧一下網絡,這是Kubernetes服務的基礎。

  • 在一個pod中的容器共享相同的網絡空間和IP。

  • 所有的pod都能通過IP彼此通信。

  • 每個節點都能看到所有的Pod,反之亦然。

  • Pod可以看到所有的服務。

那麼,在實踐中這些意味着什麼呢?

在圖中:

  • 位於Pod1中的容器B可以直接作為localhost尋址容器A

  • 容器B可以通過其IP直接尋址Pod2(kubectl get pod -o wide)。我們知道當pod2出現故障時着不是一個可靠的通信渠道,並且一個新的pod可以出現在其位置中。但是我們無法追逐不斷變化的目標。

  • 接下來,容器B可以通過Service x訪問pod 2和pod 3,後者將它們的IP與負載均衡捆綁在一起;因此,在K8S上支持基於微服務的應用程序起着至關重要的作用

儘管對Kubernetes的內部網絡結構的檢查不在本文的討論範圍內,但我稍後會發布一些參考資料以供大家進一步研究。

對於當下,我還是鼓勵你花費一點時間在實踐中經歷和理解Kubernetes中的網絡。例如,你可以啟動一個Kubernetes測試pod並且嘗試從該pod中訪問其他pod、節點和服務。此處显示的命令將在Pod內彈出一個Linux shell。

kubectl run -it networktest --image=alpine bin/ash --restart=Never --rm

現在你在Kubernetes網絡空間內並且你可以隨意使用wegtpingnslookup之類的命令進行實驗。例如,測試你的Kubernetes集群中先前列出的網絡要求,nslookup <servicename>, ping <PodIP>

現在讓我們回到我們的話題,troubleshooting Kubernetes服務,這實際上是一種網絡結構。

Step1:檢查服務是否存在

kubectl get svc

如果服務不存在,應該是服務創建出現了故障,因此要去檢查你的服務定義。

Step2:測試你的服務

請記住,一個內部的Kubernetes ClusterIP服務是無法在集群外部訪問的。因此,有兩種方法可以對其進行測試。方法一,你可以啟動一個測試Pod,通過SSH進入該pod,然後嘗試像這樣訪問你的服務:

kubectl run -it testpod --image=alpine bin/ash --restart=Never --rm

在本文中我們啟動一個alpine Docker鏡像作為pod來從其內部測試服務:

#works for http services
wget <servicename>:<httpport>

#Confirm there is a DNS entry for the service!
nslookup <servicename>

或者,你可以轉發到本地計算機並在本地進行測試。

kubectl port-forward <service_name> 8000:8080

現在,你可以通過localhost:8000訪問服務。

Step3:檢查服務是否target相關Pod

Kubernetes服務會根據標籤selector將入站流量路由到其中一個pod,流量通過其IP路由到目標Pod。所以,請檢查服務是否綁定到那些pod。

kubectl describe service <service-name> | grep Endpoints

執行上述命令之後,你應該看到與列出的工作負載相關的所有Pod的IP。如果沒有看到,請執行Step4。

Step4:檢查Pod標籤

確保在Kubernetes服務中的selector與pod的標籤相匹配。

kubectl get pods --show-labels
kubectl describe svc <service_name>

從下面的截圖的中可以看到,pod的標籤在右邊。四個pod被標記為app=tinywebsitetier=frontend,這些標籤與下面“described”的服務selector相匹配。

在這四個匹配的Pod中,只有三個正在運行,其IP在突出显示的行中被列為服務的端點(endpoint)。你還可以在IP列中看到相同的IP。

Step5:確認服務端口與pod相匹配

最後,確保在你的pod中的代碼能夠監聽到你為服務指定的targetPort(例如,你在上方截圖中看到的port8001)!

這十分簡單,為了讓你更進一步深入了解和研究Kubernetes的網絡世界,歡迎你閱讀以下文章。

  • 在Kubernetes中部署一個應用程序

  • Debug服務

  • Kubernetes網絡

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

助長毀林?巴西銷往歐洲的黃豆 至少20%來自森林砍伐

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

東南亞最大湖泊洞里薩湖延遲回流 柬埔寨歸咎上游中、寮大壩

摘錄自2020年7月22日ETtoday新聞雲報導

位於柬埔寨的洞里薩湖(Tonle Sap)是東南亞最大的湖泊,無論旱、雨季都出產大量魚蝦,周圍地帶有約300萬人以漁業相關產業維生。

洞里薩湖的水源—湄公河—通常會於雨季水位上漲,並回流至柬埔寨的洞里薩湖,提供豐富的魚類資源。但專家稱,近來連續2年湄公河都延遲回流,嚴重干擾了捕魚活動,影響上百萬人的糧食供應。

據《路透社》報導,湄公河委員會認為延遲回流現象歸因於2019年降雨減少,以及湄公河上游2座寮國和11座中國水壩的運行,破壞了湄公河的自然水流,回流預計延遲到下個月(8月)才可能發生,導致漁民生計大受影響。

生物多樣性
國際新聞
柬埔寨
洞里薩湖
水源供應
湄公河
大壩
截流
水文

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

Redis學習筆記(十八) 集群(下)

複製和故障轉移

Redis集群中的節點分為主節點(master)和從節點(slave),其中主節點用於處理槽,而從節點則用於複製某個主節點,並在被複制 的主節點下線時,代替下線主節點繼續處理命令請求。

設置從節點:CLUSTER REPLICATE < node_id >可以讓接收命令的節點稱為node_id 所指定節點的從節點,並開始對主節點進行複製。

1)接收到該命令的節點首先會在自己的clusterState.nodes字典中找到node_id所對應節點的clusterNode結構,並將自己的clusterState.myself.slaveof指針指向這個結構,以此來記錄這個節點正在複製的主節點:

struct clusterNode{
    //如果這個時一個從節點,那麼指向主節點
    struct clusterNode *slaveof;
}

2)節點修改自己的clusterState.myself.flags中的屬性,關閉原本的REDIS_NODE_MASTER標識,打開REDIS_NODE_SLAVE標識,標識這個節點已經由原來的主節點變成了從節點。

3)節點會調用複製代碼,根據clusterState.myself.slaveof指向clusterNode結構所保存的IP地址和端口號,對節點進行複製。

一個節點稱為從節點,並開始複製某個主節點這一信息會通過消息發送給集群中的其他節點,最終集群中的所有節點都會知道某個從節點正在複製某個主節點。

集群中的所有節點都會在代表主節點的clusterNode結構的slaves屬性和numslaves屬性中記錄正在複製這個主節點的從節點名單:

struct clusterNode{
    //正在複製這個主節點的從節點數量
    int numslaves;
    //數組,每個數組項指向一個正在複製這個主節點的從節點的clusterNode
    struct clusterNode **slaves;
}

集群中的每個節點都會定期地向集群中的其他節點發送PING消息,一次來檢測對方是否在線,如果接收PING消息的節點沒有在規定的時間內,向發送PING消息的節點返回PONG消息,那麼發送PING消息的節點就會將階段后PING消息的節點標記為疑似下線(PFAIL)。

集群中的各個節點會通過相互發送消息的方式來交換集群中各個節點的狀態信息:某個節點處於在線狀態、疑似下線、已下線狀態。

當一個主節點A通過罅隙得知主節點B認為主節點C進入疑似下線狀態時,主節點A會在自己的clusterState.nodes字典中找到主節點C所對應的clusterNode結構,並將主節點B的下線報告添加到clusterNode結構的fail_reports鏈表中

status clusterNode{
    list *fali_reports;//鏈表,記錄所有其他節點對該節點的下線報告
};

下線報告結構:

 

struct c;isterNodeFailReport{
    //報告目標節點已經下線的節點
    struct clusterNode *node;
    //最後一個從node節點收到下線報告的時間(程序使用這個時間戳來檢查下線報告是否過期)
    mstime_t time;
} typedef clusterNodeFailReport;

如果集群里半數以上負責處理槽的主節點都將某個主節點x報告未疑似下線,那麼這個主節點x將被標記未已下線,將主節點x標記為已下線的節點會向集群廣播一條關於主節點x的FAIL罅隙,所有收到這條罅隙的節點都會立即將主節點x標記為已下線。

故障轉移的步驟:

1)複製下線主節點的所有從節點裏面,會有一個從節點被選中,

2)被選中的從節點會執行SLAVEOF no one命令,成為新的主節點。

3)新的主節點會撤銷所有對已下線主節點的槽指派,並將這些槽指派給自己。

4)新的主節點向集群廣播一條PONG消息,這條消息讓其他集群中的其他節點立即知道這個節點已經由從節點變為主節點,並且這個主節點已經接管了原本已下線節點負責處理的槽。

5)新的主節點開始接收和自己負責處理的槽有關的命令請求,故障轉移完成。

選舉新的主節點:

1)集群的配置紀元是一個計數器。他的初始值為0;

2)當集群中的某個節點開始一次故障轉移操作時,集群配置紀元的值會被加1。

3)集群裏面每個負責處理槽的主節點都有一次投票機會,而第一個向主節點要求投票的從節點將獲得主節點的投票。

4)當從節點發現自己正在複製的主節點進入下線狀態時,從節點會向集群官博一條CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST消息,要求所有收到這個消息、並且具有投票權的主節點向這個從節點投票。

5)如果一個主節點具有投票權,並且這個主節點尚未投票給其他從節點,那麼主節點將向要求投票的從節點返回一條CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK消息,表示這個主節點支持從節點成為新的主節點。

6)每個參与選舉的從節點都會收到CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK消息,並根據自己收到了多少條這種消息來統計自己獲得了多少主節點支持。

7)如果集群中有N個具有投票權的主節點,那麼當一個從節點大於等於N/2+1張支持票時,這個從節點就當選成為新的主節點。

8)如果在一個配置紀元裏面沒有從節點收集到足夠多的支持票,那麼集群進入下一個紀元,再次進行選舉,直到選出新的主節點為止。

 

消息

集群中各個節點通過發送和接收消息來進行通信,我們稱發送消息的節點為發送者,接收消息的節點為接收者:

1)MEET消息,當發送者接到客戶端發送的CLUSTER MEET命令時,發送者會向接收者發送MEET消息,請求接收者加入到發送者當前所處的集群裏面。

2)PING消息,集群裏面的每個節點默認每隔一秒鐘就會從已知節點列表中隨機選出五個節點,然後對這五個節點中最長時間沒有發送過PING消息的節點發送PING消息,以此檢測被選中的節點是否在線。除此之外,如果節點A最後一次收到節點B發送的PONG消息的時間,距離當前時間已超過了節點A的cluster-node-timeout選項設置時長的一半,那麼節點A也會向節點B發送PING消息,這可以防止節點A因長時間沒有隨機選中節點B作為PING消息的發送對象而導致節點B的信息更新滯后。

3)PONG消息,當接收者收到發送者發來的MEET消息或者PING時,為了向發送者確認這條MEET、PING消息已到達,接收者會向發送者返回一條PONG消息。另外,一個節點也可以通過向集群發送集群廣播自己的PONG消息來讓集群中的其他節點立即刷新關於這個節點的認識。

4)FAIL消息,當一個主節點A判斷另一個主節點B已經進入FAIL狀態時,節點A會會向集群廣播一條關於節點B的FAIL消息,所有接收到這條消息的節點都會立即將節點B標記為已下線。

5)PUBLISH消息,當節點接收到一個PUBLISH命令時,節點會執行這個命令,並向集群廣播一條PUBLISH消息,所有接收到這條PUBLISH消息的節點都會執行相同的PUBLISH命令。

一條消息由消息頭(header)和消息正文(data組成)

消息頭:

typedef struct {
    //消息的長度(消息頭的長度和消息正文的長度)
    uint32_t totlen;
    //消息的類型
    uint16_t type;
    //消息正文包含的節點信息數量
    //只有發送MEET、PING、PONG這三種Gossip協議消息時使用
    uint16_t count;
    
    //薩松這所處的配置紀元
    uint64_t currentEpoch;
    //如果發送者是一個主節點,那麼這裏面記錄的時發送者的配置紀元
    //如果發送者時一個從節點,那麼這裏面記錄的時發送者正在複製的主節點的配置紀元
    uint64_t configEpoch;
    //發送者的名稱(ID)
    char sender[REDIS_CLUSTER_NAMELEN];
    //發送者目前的槽指派信息
    unsigned char myslots[REDIS_CLUSTER_SLOTS/8];
    //如果發送者是一個從節點,記錄的是發送者正在複製的主節點的名稱
    //如果發送者是一個主節點,那麼這裏記錄的是REDIS_NODE_NULL_NAME
    char slaveof[REDIS_CLUSTER_NAMELEN];
    //發送者的端口號
    uint16_t port;
    //發送者的標識值
    uint16_t flags;
    //發送者所處集群的狀態
    unsigned char state;
    //消息正文
    union clusterMsgData data;
} clusterMsg;

clusterMsg.data 結構:

union clusterMsgData{
    //MEET PING PONG 消息正文
    struct{
        //每條MEET PING PONG消息都包含兩個 clusterMsgDataGossip 結構
        clusterMsgDataGossip gossip[1]
    } ping;
    //FAIL 消息正文
    struct{
        clusterMsgDataFail about;
    } fali;
    
    //PUBLISH消息正文
    struct{
        clusterMsgDataPublish msg;
    } publish;
}

clusterMsgDataGossip結構記錄了選中節點的名字,發送者與被選中節點最後一次發送和接收PING消息和PONG消息的時間戳,被選中節點的IP地址和端口號,以及被選中節點的標識值:

typedef struct {
    //節點的名字
    char nodename[REDIS_CLUSTER_NAMELEN];
    //最後一次向該節點發送PING消息的時間戳
    uint32_t ping_sent;
    //最後一次從該 節點接收到PONG消息的時間戳
    uint32_t pong_received;
    //節點的IP地址
    char ip[16];
    //節點的端口號
    uint16_t port;
    //節點的標識值
    uint16_t flags;
} clusterMsgDataGossip;

每天學一點,總會有收穫。

 

說明:尊重作者知識產權,文中內容參考《Redis設計與實現》,僅在此做學習與大家分享。

 

 

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?