使用Kubernetes、K3s和Traefik2進行本地開發

作者簡介

Vyacheslav,擁有運維和項目管理經驗的軟件工程師

這篇文章將承接我此前搭建的本地Docker開發環境,具體步驟已經放在在以下網址:

https://github.com/Voronenko/traefik2-compose-template

除了經典的docker化的項目之外,我還有其他的Kubernetes項目。儘管Kubernetes已經成為容器編排的事實標準,但是不得不承認Kubernetes是一個既消耗資源又消耗金錢的平台。由於我並不經常需要外部集群,因此我使用輕量級K3s發行版來進行Kubernetes本地開發。

K3s是為IoT和邊緣計算而構建的經過認證的Kubernetes發行版之一,還能夠按產品規模部署到VM。

我使用K3s的方式是這樣的:在我的工作筆記本上本地安裝K3s,儘管有時我需要在本地部署較重的測試工作負載,為此,我準備了兩個神器——兩個運行ESXi的外部Intel NUCs。

默認情況下,K3s安裝Traefik 1.x作為ingress,如果你對此十分滿意,那麼無需往下繼續閱讀了。

在我的場景中,我同時會牽涉到好幾個項目,特別是經典的docker和docker swarm,因此我經常遇到在獨立模式下部署Traefik的情況。

因此,本文其餘部分將深入介紹如何將外部traefik2配置為K3s集群的ingress。

安裝Kubernetes K3s系列集群

你可以按照常規方式使用命令curl -sfL https://get.k3s.io | sh -安裝K3s,或者你可以使用輕量實用程序k3sup安裝(https://github.com/alexellis/k3sup)。具體步驟在之前的文章介紹過。

與我們的設置不同的是,我們使用命令--no-deploy traefik專門安裝了不帶traefik組件的K3s。

export CLUSTER_MASTER=192.168.3.100
export CLUSTER_DEPLOY_USER=slavko
k3sup install --ip $CLUSTER_MASTER --user $CLUSTER_DEPLOY_USER --k3s-extra-args '--no-deploy traefik'

執行后,你將獲得使用kubectl所需的連接詳細信息。安裝K3s后,你可以快速檢查是否可以看到節點。

# Test your cluster with - export path to k3s cluster kubeconfig:
export KUBECONFIG=/home/slavko/kubeconfig
kubectl get node -o wide

注:這裏沒有固定的安裝模式,你甚至可以使用docker-compose自行啟動它。

server:
  image: rancher/k3s:v0.8.0
  command: server --disable-agent --no-deploy traefik
  environment:
    - K3S_CLUSTER_SECRET=somethingtotallyrandom
    - K3S_KUBECONFIG_OUTPUT=/output/kubeconfig.yaml
    - K3S_KUBECONFIG_MODE=666
  volumes:
    # k3s will generate a kubeconfig.yaml in this directory. This volume is mounted
    # on your host, so you can then 'export KUBECONFIG=/somewhere/on/your/host/out/kubeconfig.yaml',
    # in order for your kubectl commands to work.
    - /somewhere/on/your/host/out:/output
    # This directory is where you put all the (yaml) configuration files of
    # the Kubernetes resources.
    - /somewhere/on/your/host/in:/var/lib/rancher/k3s/server/manifests
  ports:
    - 6443:6443

node:
  image: rancher/k3s:v0.8.0
  privileged: true
  links:
    - server
  environment:
    - K3S_URL=https://server:6443
    - K3S_CLUSTER_SECRET=somethingtotallyrandom
  volumes:
    # this is where you would place a alternative traefik image (saved as a .tar file with
    # 'docker save'), if you want to use it, instead of the traefik:v2.0 image.
    - /sowewhere/on/your/host/custom-image:/var/lib/rancher/k3s/agent/images

配置Traefik 2,與Kubernetes一起使用

在文章開頭提到的鏈接中,我已經在我的系統中安裝了Traefik 2,並根據該鏈接內容,服務於一些需求。現在是時候配置Traefik 2 Kubernetes後端了。

Traefik 2使用CRD(自定義資源定義)來完成這一點。定義的最新示例可以在以下鏈接中找到,但這些示例僅適用於Traefik 2也作為Kubernetes工作負載的一部分執行的情況:

https://docs.traefik.io/reference/dynamic-configuration/kubernetes-crd/

對於外部Traefik 2,我們僅需要以下描述的定義子集。

我們引入一系列自定義資源定義,以允許我們來描述我們的Kubernetes服務將會如何暴露到外部,traefik-crd.yaml

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: ingressroutes.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: IngressRoute
    plural: ingressroutes
    singular: ingressroute
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: ingressroutetcps.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: IngressRouteTCP
    plural: ingressroutetcps
    singular: ingressroutetcp
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: middlewares.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: Middleware
    plural: middlewares
    singular: middleware
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: tlsoptions.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: TLSOption
    plural: tlsoptions
    singular: tlsoption
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: traefikservices.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: TraefikService
    plural: traefikservices
    singular: traefikservice
  scope: Namespaced  

同時,我們需要集群角色traefik-ingress-controller,以提供對服務、端點和secret的只讀訪問權限以及自定義的traefik.containo.us組,traefik-clusterrole.yaml

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: traefik-ingress-controller

rules:
  - apiGroups:
      - ""
    resources:
      - services
      - endpoints
      - secrets
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
    resources:
      - ingresses/status
    verbs:
      - update
  - apiGroups:
      - traefik.containo.us
    resources:
      - middlewares
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - traefik.containo.us
    resources:
      - ingressroutes
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - traefik.containo.us
    resources:
      - ingressroutetcps
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - traefik.containo.us
    resources:
      - tlsoptions
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - traefik.containo.us
    resources:
      - traefikservices
    verbs:
      - get
      - list
      - watch

最後,我們需要系統服務賬號traefik-ingress-controller與之前創建的集群角色traefik-ingress-controller相關聯。

---
kind: ServiceAccount
apiVersion: v1
metadata:
  namespace: kube-system
  name: traefik-ingress-controller

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: traefik-ingress-controller

roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: traefik-ingress-controller
subjects:
  - kind: ServiceAccount
    name: traefik-ingress-controller
    namespace: kube-system

我們應用以上資源之後:

apply:
  kubectl apply -f traefik-crd.yaml
  kubectl apply -f traefik-clusterrole.yaml
  kubectl apply -f traefik-service-account.yaml

我們已經準備好開始調整Traefik 2

將Traefik 2指向K3s集群

根據Traefik文檔的建議,當Traefik部署到Kubernetes中時,它將讀取環境變量KUBERNETES_SERVICE_HOST和KUBERNETES_SERVICE_PORT或KUBECONFIG來構造端點。

/var/run/secrets/kubernetes.io/serviceaccount/token中查找訪問token,而SSL CA證書將在/var/run/secrets/kubernetes.io/serviceaccount/ca.crt.中查找。當部署到Kubernetes內部時,兩者都會自動提供掛載。

當無法找到環境變量時,Traefik會嘗試使用external-cluster客戶端連接到Kubernetes API server。這一情況下,需要設置endpoint。具體來說,可以將其設置為kubectl代理使用的URL,以使用相關的kubeconfig授予的身份驗證和授權連接到Kubernetes集群。

Traefik 2可以使用任何受支持的配置類型來靜態配置-toml、yaml或命令行交換。

[providers.kubernetesCRD]
  endpoint = "http://localhost:8080"
  token = "mytoken"
providers:
  kubernetesCRD:
    endpoint = "http://localhost:8080"
    token = "mytoken"
    # ...
--providers.kubernetescrd.endpoint=http://localhost:8080 
--providers.kubernetescrd.token=mytoken

第一次運行時,如果你在外部有Traefik,很有可能沒有traefik-ingress-controller訪問token來指定mytoken。那麼,你需要執行以下命令:

# Check all possible clusters, as your .KUBECONFIG may have multiple contexts:
kubectl config view -o jsonpath='{"Cluster name\tServer\n"}{range .clusters[*]}{.name}{"\t"}{.cluster.server}{"\n"}{end}'

# Output kind of
# Alias tip: k config view -o jsonpath='{"Cluster name\tServer\n"}{range .clusters[*]}{.name}{"\t"}{.cluster.server}{"\n"}{end}'
# Cluster name  Server
# default  https://127.0.0.1:6443

# You are interested in: "default", if you did not name it differently

# Select name of cluster you want to interact with from above output:
export CLUSTER_NAME="default"

# Point to the API server referring the cluster name
export APISERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name==\"$CLUSTER_NAME\")].cluster.server}")
# usually https://127.0.0.1:6443

# Gets the token value
export TOKEN=$(kubectl get secrets -o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='traefik-ingress-controller')].data.token}" --namespace kube-system|base64 --decode)

# Explore the API with TOKEN

如果成功了,你應該收到以下響應:

{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "192.168.3.100:6443"
    }
  ]

以及一些事實,如token:

eyJhbGciOiJSUzI1NiIsImtpZCI6IjBUeTQyNm5nakVWbW5PaTRRbDhucGlPeWhlTHhxTXZjUDJsRmNacURjVnMifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJ0cmFlZmlrLWluZ3Jlc3MtY29udHJvbGxlci10b2tlbi12emM3diIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJ0cmFlZmlrLWluZ3Jlc3MtY29udHJvbGxlciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImQ5NTc3ZTkxLTdlNjQtNGMwNi1iZDgyLWNkZTk0OWM4MTI1MSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTp0cmFlZmlrLWluZ3Jlc3MtY29udHJvbGxlciJ9.Mk8EBS4soO8uX-uSnV3o4qZKR6Iw6bgeSmPhHbJ2fjuqFgLnLh4ggxa-N9AqmCsEWiYjSi5oKAu986UEC-_kGQh3xaCYsUwlkM8147fsnwCbomSeGIct14JztVL9F8JwoDH6T0BOEjn-J9uY8-fUKYL_Y7uTrilhFapuILPsj_bFfgIeOOapRD0XshKBQV9Qzg8URxyQyfzl68ilm1Q13h3jLj8CFE2RlgEUFk8TqYH4T4fhfpvV-gNdmKJGODsJDI1hOuWUtBaH_ce9w6woC9K88O3FLKVi7fbvlDFrFoJ2iVZbrRALPjoFN92VA7a6R3pXUbKebTI3aUJiXyfXRQ

根據上次響應的API server的外部地址:https://192.168.3.100:6443

同樣,提供的token中沒有任何特殊之處:這是JWT的token,你可以使用https://jwt.io/#debugger-io,檢查它的內容。

{
  "alg": "RS256",
  "kid": "0Ty426ngjEVmnOi4Ql8npiOyheLxqMvcP2lFcZqDcVs"
}
{
  "iss": "kubernetes/serviceaccount",
  "kubernetes.io/serviceaccount/namespace": "kube-system",
  "kubernetes.io/serviceaccount/secret.name": "traefik-ingress-controller-token-vzc7v",
  "kubernetes.io/serviceaccount/service-account.name": "traefik-ingress-controller",
  "kubernetes.io/serviceaccount/service-account.uid": "d9577e91-7e64-4c06-bd82-cde949c81251",
  "sub": "system:serviceaccount:kube-system:traefik-ingress-controller"
}

正確的配置非常重要,因此請確保對APISERVER的兩個調用均返回合理的響應。

export APISERVER=YOURAPISERVER
export TOKEN=YOURTOKEN

curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure

curl -X GET $APISERVER/api/v1/endpoints --header "Authorization: Bearer $TOKEN" --insecure

創建其他訪問token

控制器循環確保每個服務賬戶都有一個帶有API token的secret,可以像我們之前那樣被發現。

此外,你還可以為一個服務賬戶創建額外的token,創建一個ServiceAccountToken類型的secret,併為服務賬戶添加一個註釋,控制器會用生成的token來更新它。

---
apiVersion: v1
kind: Secret
namespace: kube-system
metadata:
  name: traefik-manual-token
  annotations:
    kubernetes.io/service-account.name: traefik-ingress-controller
type: kubernetes.io/service-account-token

# Any tokens for non-existent service accounts will be cleaned up by the token controller.

# kubectl describe secrets/traefik-manual-token

用以下命令創建:

kubectl create -f ./traefik-service-account-secret.yaml
kubectl describe secret traefik-manual-token

刪除/無效:

kubectl delete secret traefik-manual-token

對外部traefik 2的更改構成定義

我們需要在文章開頭給出的鏈接中獲得的traefik2配置進行哪些更改?

https://github.com/Voronenko/traefik2-compose-template

a) 我們在新文件夾kubernetes_data中存儲ca.crt文件,該文件用於驗證對Kubernetes授權的調用。這是可以在kubeconfig文件的clusters-> cluster-> certificate-authority-data下找到的證書。

該volume將映射在/var/run/secrets/kubernetes.io/serviceaccount下以獲取官方Traefik 2鏡像

volumes:
    ...
      - ./kubernetes_data:/var/run/secrets/kubernetes.io/serviceaccount

b) 調整Traefik 2 kubernetescrd後端以提供3個參數:endpoint、證書路徑和token。請注意,作為外部Traefik作為docker容器,你需要指定正確的endpoint地址,並確保以安全的方式進行。

  - "--providers.kubernetescrd=true"
      - "--providers.kubernetescrd.endpoint=https://192.168.3.100:6443"
      - "--providers.kubernetescrd.certauthfilepath=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
      - "--providers.kubernetescrd.token=YOURTOKENWITHOUTANYQUOTES

如果你都執行正確了,那麼你現在應該在Traefik UI上看到了一些希望。如果你沒有看到traefik,或者在運行Traefik時有問題,你可以查看之後的故障排除部分。

現在是時候通過Trafik 2暴露一些Kubernetes服務了,以確保Traefik 2能夠作為ingress工作。讓我們來看經典案例whoami服務,whoami-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: whoami

spec:
  ports:
    - protocol: TCP
      name: web
      port: 80
  selector:
    app: whoami

---
kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: default
  name: whoami
  labels:
    app: whoami

spec:
  replicas: 2
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
        - name: whoami
          image: containous/whoami
          ports:
            - name: web
              containerPort: 80

並且以http或https的方式暴露它,whoami.k.voronenko.net全限定域名下的whoami-ingress-route.yaml

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: ingressroute-notls
  namespace: default
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`whoami.k.voronenko.net`)
      kind: Rule
      services:
        - name: whoami
          port: 80

---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: ingressroute-tls
  namespace: default
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`whoami.k.voronenko.net`)
      kind: Rule
      services:
        - name: whoami
          port: 80
  tls:
    certResolver: default

然後應用它:

kubectl apply -f whoami-service.yaml
  kubectl apply -f whoami-ingress-route.yaml

應用后,你應該會在Traefik dashboard上看到一些希望,即KubernetesCRD後端。

正如你所看到的,Traefik已經檢測到我們的K3s Kubernetes集群上運行的新工作負載,而且它與我們在同一個盒子上的經典Docker工作負載(如portainer)很好地共存。

讓我們檢查一下Traefik 2是否將Traefik路由到了我們的Kubernetes工作負載:如你所見,你可以在http和https endpoint上成功地接觸到whoami工作負載,瀏覽器接受你的證書為可信任的“綠標籤”。

我們的目標達到了!我們在本地筆記本上配置了Traefik 2。Traefik 2將你的docker或Kubernetes工作流暴露在http或https endpoint上。帶可選的 letsencrypt 的 Traefik 2 將負責 https。

故障排查

正如你所知,在配置過程可能存在多個問題,你可以考慮使用一些分析工具,如:

https://github.com/Voronenko/dotfiles/blob/master/Makefile#L185

我特別建議:

a) VMWare octant:這是一個基於Web的功能強大的Kubernetes dashboard,你可以在上面使用你的kubeconfig

b) Rakess:這是一個獨立工具也是一個kubectl插件,用於显示Kubernetes服務器資源的訪問矩陣(https://github.com/corneliusweig/rakkess)

檢查系統賬戶的憑據

rakkess --sa kube-system:traefik-ingress-controller

c) kubectl

檢查哪些角色與服務賬戶相關聯

kubectl get clusterrolebindings -o json | jq -r '
  .items[] |
  select(
    .subjects // [] | .[] |
    [.kind,.namespace,.name] == ["ServiceAccount","kube-system","traefik-ingress-controller"]
  ) |
  .metadata.name'

d) Traefik 文檔:例如kubernetescrd後端提供了更多配置開關的方式。

--providers.kubernetescrd  (Default: "false")
        Enable Kubernetes backend with default settings.
    --providers.kubernetescrd.certauthfilepath  (Default: "")
        Kubernetes certificate authority file path (not needed for in-cluster client).
    --providers.kubernetescrd.disablepasshostheaders  (Default: "false")
        Kubernetes disable PassHost Headers.
    --providers.kubernetescrd.endpoint  (Default: "")
        Kubernetes server endpoint (required for external cluster client).
    --providers.kubernetescrd.ingressclass  (Default: "")
        Value of kubernetes.io/ingress.class annotation to watch for.
    --providers.kubernetescrd.labelselector  (Default: "")
        Kubernetes label selector to use.
    --providers.kubernetescrd.namespaces  (Default: "")
        Kubernetes namespaces.
    --providers.kubernetescrd.throttleduration  (Default: "0")
        Ingress refresh throttle duration
    --providers.kubernetescrd.token  (Default: "")
        Kubernetes bearer token (not needed for in-cluster client).
    --providers.kubernetesingress  (Default: "false")
        Enable Kubernetes backend with default settings.
    --providers.kubernetesingress.certauthfilepath  (Default: "")
        Kubernetes certificate authority file path (not needed for in-cluster client).
    --providers.kubernetesingress.disablepasshostheaders  (Default: "false")
        Kubernetes disable PassHost Headers.
    --providers.kubernetesingress.endpoint  (Default: "")
        Kubernetes server endpoint (required for external cluster client).
    --providers.kubernetesingress.ingressclass  (Default: "")
        Value of kubernetes.io/ingress.class annotation to watch for.
    --providers.kubernetesingress.ingressendpoint.hostname  (Default: "")
        Hostname used for Kubernetes Ingress endpoints.
    --providers.kubernetesingress.ingressendpoint.ip  (Default: "")
        IP used for Kubernetes Ingress endpoints.
    --providers.kubernetesingress.ingressendpoint.publishedservice  (Default: "")
        Published Kubernetes Service to copy status from.
    --providers.kubernetesingress.labelselector  (Default: "")
        Kubernetes Ingress label selector to use.
    --providers.kubernetesingress.namespaces  (Default: "")
        Kubernetes namespaces.
    --providers.kubernetesingress.throttleduration  (Default: "0")
        Ingress refresh throttle duration
    --providers.kubernetesingress.token  (Default: "")
        Kubernetes bearer token (not needed for in-cluster client).

e) 確保Traefik有足夠的權限可以訪問apiserver endpoint

如果你希望Traefik為你查詢信息:通過在配置中放置一些錯誤的apiserver地址,可以查看訪問的endpoint和查詢順序。有了這些知識和你的Traefik Kubernetes token,你就可以使用Traefik憑證檢查這些endpoint是否可以訪問。

traefik_1    | E0421 12:30:12.624877       1 reflector.go:125] pkg/mod/k8s.io/client-go@v0.0.0-20190718183610-8e956561bbf5/tools/cache/reflector.go:98: Failed to list *v1.Endpoints: Get https://192.168.3.101:6443/api/v1/endpoints?limit=500&resourceVersion=0:
traefik_1    | E0421 12:30:12.625341       1 reflector.go:125] pkg/mod/k8s.io/client-go@v0.0.0-20190718183610-8e956561bbf5/tools/cache/reflector.go:98: Failed to list *v1.Service: Get https://192.168.3.101:6443/api/v1/services?limit=500&resourceVersion=0:
traefik_1    | E0421 12:30:12.625395       1 reflector.go:125] pkg/mod/k8s.io/client-go@v0.0.0-20190718183610-8e956561bbf5/tools/cache/reflector.go:98: Failed to list *v1beta1.Ingress: Get https://192.168.3.101:6443/apis/extensions/v1beta1/ingresses?limit=500&resourceVersion=0:
traefik_1    | E0421 12:30:12.625449       1 reflector.go:125] pkg/mod/k8s.io/client-go@v0.0.0-20190718183610-8e956561bbf5/tools/cache/reflector.go:98: Failed to list *v1alpha1.Middleware: Get https://192.168.3.101:6443/apis/traefik.containo.us/v1alpha1/middlewares?limit=500&resourceVersion=0:
traefik_1    | E0421 12:30:12.625492       1 reflector.go:125] pkg/mod/k8s.io/client-go@v0.0.0-20190718183610-8e956561bbf5/tools/cache/reflector.go:98: Failed to list *v1alpha1.IngressRoute: Get https://192.168.3.101:6443/apis/traefik.containo.us/v1alpha1/ingressroutes?limit=500&resourceVersion=0:
traefik_1    | E0421 12:30:12.625531       1 reflector.go:125] pkg/mod/k8s.io/client-go@v0.0.0-20190718183610-8e956561bbf5/tools/cache/reflector.go:98: Failed to list *v1alpha1.TraefikService: Get https://192.168.3.101:6443/apis/traefik.containo.us/v1alpha1/traefikservices?limit=500&resourceVersion=0:
traefik_1    | E0421 12:30:12.625572       1 reflector.go:125] pkg/mod/k8s.io/client-go@v0.0.0-20190718183610-8e956561bbf5/tools/cache/reflector.go:98: Failed to list *v1alpha1.TLSOption: Get https://192.168.3.101:6443/apis/traefik.containo.us/v1alpha1/tlsoptions?limit=500&resourceVersion=0:
traefik_1    | E0421 12:30:12.625610       1 reflector.go:125] pkg/mod/k8s.io/client-go@v0.0.0-20190718183610-8e956561bbf5/tools/cache/reflector.go:98: Failed to list *v1alpha1.IngressRouteTCP: Get https://192.168.3.101:6443/apis/traefik.containo.us/v1alpha1/ingressroutetcps?limit=500&resourceVersion=0:

f) 記錄K3s本身

安裝腳本將自動檢測你的操作系統是使用systemd還是openrc並啟動服務。使用openrc運行時,將在/var/log/k3s.log中創建日誌。使用systemd運行時,將在/var/log/syslog中創建日誌,並使用journalctl -u k3s查看。

在那裡,你可能會得到一些提示,例如:

кві 21 15:42:44 u18d k3s[612]: E0421 15:42:44.936960     612 authentication.go:104] Unable to authenticate the request due to an error: invalid bearer token

這將為你提供有關K8s Traefik起初使用時出現問題的線索,Enjoy your journey!

相關代碼你可以在以下鏈接中找到:

https://github.com/Voronenko/k3s-mini

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

【其他文章推薦】

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

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

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

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

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

※超省錢租車方案

.NET Core請求控制器Action方法正確匹配,但為何404?

前言

有些時候我們會發現方法名稱都正確匹配,但就是找不到對應請求接口,所以本文我們來深入了解下何時會出現接口請求404的情況。

匹配控制器Action方法(404)

首先我們創建一個web api應用程序,我們給出如下示例控制器代碼

[ApiController]
[Route("[controller]/[action]")]
public class WeatherController : ControllerBase
{
    [HttpGet]
    string Get()
    {
        return "Hello World";
    }
}

 

當我們進行如上請求時會發現接口請求不到,這是為何呢?細心的你應該可能發現了,對於請求方法是私有,而不是公共的,當我們加上public就可以請求到了接口

[HttpGet("get")]
public string Get()
{
    return "Hello World";
}

匹配控制器Action方法本質

經過如上示例,那麼對於Action方法的到底要滿足怎樣的定義才能夠不至於請求不到呢?接下來我們看看源碼怎麼講。我們找到DefaultApplicationModelProvider類,在此類中有一個OnProvidersExecuting方法用來構建控制器和Action方法模型,當我們構建完畢所有滿足條件的控制器模型后,緊接着勢必會遍歷控制器模型去獲取對應控制器模型下的Action方法,這裏只截取獲取Action方法片段,源碼如下:

foreach (var controllerType in context.ControllerTypes)
{    
    //獲取控制器模型下的Action方法
    foreach (var methodInfo in controllerType.AsType().GetMethods())
    {
        var actionModel = CreateActionModel(controllerType, methodInfo);
        if (actionModel == null)
        {
            continue;
        }

        actionModel.Controller = controllerModel;
        controllerModel.Actions.Add(actionModel);    
    }
}

上述紅色標記則是創建Action模型的重點,我們繼續往下看到底滿足哪些條件才創建Action模型呢?

protected virtual ActionModel CreateActionModel(TypeInfo typeInfo, MethodInfo methodInfo)
{
    if (typeInfo == null)
    {
        throw new ArgumentNullException(nameof(typeInfo));
    }

    if (methodInfo == null)
    {
        throw new ArgumentNullException(nameof(methodInfo));
    }

    if (!IsAction(typeInfo, methodInfo))
    {
        return null;
    }    
    ......    
}

到了這個方法裏面,我們找到了如何確定一個方法為Action方法的源頭,由於該方法有點長,這裏我採用文字敘述來作為判斷邏輯,如下:

protected virtual bool IsAction(TypeInfo typeInfo, MethodInfo methodInfo)
{
    //如果有屬性訪問器(無效)

    //如果有NonAction特性標識無效)

    //如果重寫Equals(Object), GetHashCode()方法(無效)

    //如果實現Dispose方法(無效)

    //如果是靜態方法(無效)

    //如果是抽象方法(無效)

    //如果是構造函數(無效)

    //如果是泛型方法(無效)

    //必須為公共方法
    return methodInfo.IsPublic;
}

如上是從方法定義的角度來過濾而獲取Action方法,除此之外,我們請求方法的名稱還可以自定義,比如通過路由、ActionName特性指定,那麼這二者是否存在優先級呢?比如如下示例:

[ApiController]
[Route("[controller]/[action]")]
public class WeatherController : ControllerBase
{
    [HttpGet]
    [ActionName("get1")]
    public string get()
    {
        var routeValue = HttpContext.Request.RouteValues.FirstOrDefault();

        return routeValue.Value.ToString();
    }
}

我們可以看到此時將以ActionName特性作為方法名稱。所以在上述過濾方法定義后開始構建方法模型,在此之後還會再做一步操作,那就是查找該方法是否通過ActionName特性標識,若存在則以ActionName特性標識給定的名稱作為請求方法名稱,否則以方法定義名稱為準,源碼如下:

var actionModel = new ActionModel(methodInfo, attributes);

AddRange(actionModel.Filters, attributes.OfType<IFilterMetadata>());

var actionName = attributes.OfType<ActionNameAttribute>().FirstOrDefault();
if (actionName?.Name != null)
{
    actionModel.ActionName = actionName.Name;
}
else
{
    actionModel.ActionName = methodInfo.Name;
}

還沒完,若是將路由特性放到Action方法上,如下,此時請求接口應該是weather/get還是weather/get1呢?

[ApiController]
public class WeatherController : ControllerBase
{
    [HttpGet]
    [Route("weather/get")]
    [ActionName("get1")]
    public string get()
    {
        var routeValue = HttpContext.Request.RouteValues.FirstOrDefault();

        return routeValue.Value.ToString();
    }
}

此時若我們以weather/get1請求將出現404,還是以路由特性模板給定為準進行請求,但最終會將路由上Action方法名稱通過ActionName特性上的名稱賦值給Action模型中的ActionName進行覆蓋,源碼如下,所以上述我們得到的action名稱為get1,,當然這麼做沒有任何實際意義。

public static void AddRouteValues(ControllerActionDescriptor actionDescriptor,ControllerModel controller,ActionModel action)
{
    foreach (var kvp in action.RouteValues)
    {
        if (!actionDescriptor.RouteValues.ContainsKey(kvp.Key))
        {
            actionDescriptor.RouteValues.Add(kvp.Key, kvp.Value);
        }
    }

    if (!actionDescriptor.RouteValues.ContainsKey("action"))
    {
        actionDescriptor.RouteValues.Add("action", action.ActionName ?? string.Empty);
    }

    if (!actionDescriptor.RouteValues.ContainsKey("controller"))
    {
        actionDescriptor.RouteValues.Add("controller", controller.ControllerName);
    }
}

總結

本文我們只是單獨針對查找Action方法名稱匹配問題做了進一步的探討,根據源碼分析,對Action方法名稱指定會做3步操作:第一,根據方法定義進行過濾篩選,第二,若方法通過AcionName特性標識則以其所給名稱為準,否則以方法名稱為準,最終賦值給ActionModel上的ActionName屬性,第三,將ActionModel上的ActionName值賦值給路由集合中的鍵Action。

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

【其他文章推薦】

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

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

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

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

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

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

大陸代工給鴻海?特斯拉駁斥傳言

美國電動車廠特斯拉交貨能力大幅提升,出現逾 7 成的成長,面對會否將代工業務拉回大陸時,特斯拉卻傾向冷處理,甚至還主動發出官方回應,強調「目前沒有在大陸代工生產的計畫」,看來先前外界傳出鴻海要在中國替 Tesla 代工電動車的合作計畫,恐怕還要再等一等。   特斯拉 2013 年共交付 2 萬輛 Model S,2014 年有機會上看 3.5 萬輛,市場將特斯拉交貨能力大增原因指向生產線的擴展,特斯拉美國生產基地最近又新增了一條生產線,周產能達 1,000 輛。   除了在美擴充生產線,會否將代工產線拉回大陸,也成了市場關注焦點,但對此,特斯拉卻傾向冷處理,還特別發出官方回應,強調「特斯拉現所有在華銷售的車輛都是在美國生產,再進口到中國,目前沒有在大陸代工生產的計畫。」  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

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

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

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

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

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

衣索比亞總理阿邁德推動環保、性平獲2019年諾貝爾和平獎

貝爾和平獎11日出爐,得獎者是衣索比亞總理阿邁德(Abiy Ahmed),原因是他結束該國與鄰國厄利垂亞之間長達20年的戰火,這項創舉又激發了非洲地區一系列的外交突破,阿邁德也提倡性別平等、環境保護。

阿邁德2018年4月上任,是該國第1位奧羅莫元首,在最初幾個月,他果斷、大膽地釋放政治犯,並對他們受到的酷刑予以譴責,也釋放被監禁的記者,甚至與政治反對派、民間社會對談,討論改革問題,並邀請先前流亡的政黨人士返國,還針對安全、司法部門進行重大改革。

阿邁德也致力於性別、環保問題,例如在國境內植樹造林以遏制氣候變化的負面影響。

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

【其他文章推薦】

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

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

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

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

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

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

談談 Promise 以及實現 Fetch 的思路

Promise 是異步編程的一種解決方案。

Promise


/**
 * 屬性
 */
Promise.length
Promise.prototype

/**
 * 方法
 */
Promise.all(iterable)   // 所有成功觸發成功  任何失敗觸發失敗
Promise.race(iterable)  // 任意一個成功或失敗后觸發
Promise.reject(reason)
Promise.resolve(value)

/**
 * 原型
 */
Promise.prototype.constructor
//方法
Promise.prototype.catch(onRejected)
Promise.prototype.then(onFulfilled, onRejected)
Promise.prototype.finally(onFinally)

Promise 有三種狀態

  • pending: 初始狀態,既不是成功,也不是失敗狀態。
  • resolve: 意味着操作成功完成。(resoloved)
  • reject: 意味着操作失敗。

pending

pending 是初始狀態,執行 resolve/reject 會進入對應狀態,如果不執行,責一直為 pending 狀態

例如下面代碼,promise 將一直在 pending 狀態,不會執行 then/catch.

new Promise(function (resolve, reject) { })
  .then(res => console.log(res))
  .catch(err => console.log(err))

resolve

resolve 意味着操作成功完成, 如果有 .then,值會傳入 .then 的第一個參數函數里。

new Promise(function (resolve, reject) {
  resolve(1)
})
  .then(res => console.log(res))

then 的第一個參數是成功的回調,第一個參數的返回值會影響接下來鏈的去向。第一個參數的返回值一般有三種情況

  • 無返回值:會去執行下一個 .then ,沒有參數
  • 返回值非promise:調用下一個then的函數,參數為返回值
  • 返回值為promise:根據promise的執行結果,執行 下一個then/catch,如果一直是pending,則不執行下一個then/catch

例如想要在當前 then 終止,可以這樣操作:

  .then((res) => new Promise(() => {}))

reject

reject 意味着操作失敗。

使用 .catch 會捕獲到錯誤信息。

與代碼報錯(如 undefined.a)不同的是, 代碼報錯如果不使用 catch 捕獲,會向外傳遞,最終傳遞到根結點;而 reject 屬於 promise 錯誤,即使不使用 catch 捕獲也不會對全局有影響。

用 promise 實現 fetch

先來看幾個問題:

  1. 如果請求 code 404, 會走 then 還是 catch? (答案:then)
  2. 控制台能看到一行 404 的錯誤, 為什麼還是走 then 不是 catch 呢
  3. 如果請求跨域失敗,走 then 還是 catch?(答案:catch)
  4. 同樣是控制台看到錯誤,兩者有什麼區別呢?
  5. 跨域失敗的報錯, 和 then 中 undefined.a 報錯,如果都不 catch,後者在 react 腳手架開發環境頁面會蹦,兩者有什麼區別?

帶着這幾個問題,來看看 fetch。

fetch 返回值是 promise,所以有三種狀態 pending、resolve、reject.

  • pending: 請求中
  • resolve: 請求成功(code 200/404/500 等, 非 200 控制台輸出錯誤)
  • reject: 請求失敗(跨域失敗、連接超時、無網絡等,控制台輸出錯誤)

我們還發現,請求失敗時,只能 catch 到最後一行錯誤, 如圖

捕獲后

為什麼 404 在控制台看到錯誤,還走 then, resolve 如何實現

實現有幾個難點,

  1. throw 後面代碼不會執行;
  2. 先報錯,后執行 then;
  3. catch 后錯誤不會打印在控制台;

試了下,Promise.reject(‘xxx’) 這樣的報錯方式雖然是微觀任務,但是總是在.then之後才在控制台輸出,更像是宏觀任務。所以也加個setTImeout宏觀任務調至後面。

var fetch = function () {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      if ('請求成功 200') {
        resolve('Response數據結構');
      } else if ('請求成功 404,500等') {
        Promise.reject('GET xxxxxxxx 404');
        setTimeout(function () {
          resolve('Response數據結構');
        });
      }
    })
  })
}

請求失敗 例如跨域失敗 reject 如何實現呢

同樣加個 setTimeout

var fetch = function () {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      if ('請求成功 200') {
        resolve('Response數據結構');
      } else if ('請求成功 404,500等') {
        Promise.reject('GET xxxxxxxx 404');
        setTimeout(function () {
          resolve('Response數據結構');
        });
      } else if ('請求失敗') {
        Promise.reject('Access to fetch xxxxx with CORS disabled.');
        Promise.reject('GET xxxxx net::ERR_FAILED');
        setTimeout(function () {
          reject('TypeError: Failed to fetch');
        });
      }
    })
  })
}

還是有些問題,我們實現的因為在promise 中,錯誤會有前綴 Uncaught (in promise)。瀏覽器客戶端應該有更好的實現方式。

最後總結一下 fetch 的三種情況

  • pending: 請求中
  • resolve: 請求成功(code 200: 調用 resolve 返回數據; code: 404/500 等, 先拋錯,再調用 resolve 返回數據。)
  • reject: 請求失敗(跨域失敗、連接超時、無網絡等,先控制台拋錯,再調用 reject)

拋錯均不影響代碼執行,與 undefined.a 不同。

whosmeya.com

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

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

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

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

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

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

2015年京津冀公共服務新能源車將達20222輛

22日,中國工信部、發改委及科技部等七部委聯合印發《京津冀公交等公共服務領域新能源汽車推廣工作方案》,提出2014年到2015年,京津冀地區公共交通服務領域共推廣20,222輛新能源汽車。其中北京市8,507輛,天津市6,000輛,河北省5,715輛,京津冀地區公交車中新能源汽車到2015年底比例不低於16%,京津出租車中新能源汽車比例不低於5%。   2014年到2015年,京津冀地區共新建充/換電站94座,充電樁新增1.62萬個。到2015年底,京津冀地區充換電站總數將達到112座,充電樁總數將達到19,657個,基本建成以保障運行為前提,建設規模適度超前的充電設施網絡。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

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

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

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

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

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

大數據:全球1/3碳排放 來自這20間公司

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

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

【其他文章推薦】

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

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

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

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

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

DNS篇(詳解DNS)

*文章來源:https://blog.egsec.cn/archives/601

*本文將主要說明:本文主要敘述什麼是DNS、域名的層級、DNS 解析過程、DNS的緩存時間、DNS 的記錄類型、DNS 報文結構、DNS劫持與HTTP劫持以及手動清理本地緩存的方法。

 

DNS屬於應用層。DNS即域名系統,其作用是將字符串域名解析成相對於的服務器IP地址,免除人們記憶IP地址的單調和苦惱,屬於為用戶排憂解難之舉,因此劃歸為應用層。DNS不屬於協議,它是域名解析。

 

什麼是DNS

DNS是 Domain Name System 的縮寫,也就是 域名解析系統,它的作用非常簡單,就是根據域名查出對應的 IP地址。

你可以把它想象成一本巨大的電話本,比如當你要訪問域名www.egsec.cn,首先要通過DNS查出它的IP地址是118.31.61.137。

域名層級

DNS 的解析過程中,需要對域名的層級有了解:

  • 根域名 :.root 或者 . ,通常是省略的
  • 頂級域名,如 .com,.cn 等
  • 次級域名,如 baidu.com 里的 baidu,這個是用戶可以進行註冊購買的
  • 主機域名,比如 baike.baidu.com 里的baike,這個是用戶可分配的 
主機名.次級域名.頂級域名.根域名
baike.baidu.com.root

DNS 解析過程

咱們以訪問 www.egsec.cn 這個域名為例,來看一看當你訪問 www.egsec.cn 時,會發生哪些事:

  1. 先查找本地 DNS 緩存(自己的電腦上),有則返回,沒有則進入下一步
  2. 查看本地 hosts 文件有沒有相應的映射記錄,有則返回,沒有則進入下一步
  3. 向本地 DNS 服務器(一般都是你的網絡接入服務器商提供,比如中國電信,中國移動)發送請求進行查詢,本地DNS服務器收到請求后,會先查下自己的緩存記錄,如果查到了直接返回就結束了,如果沒有查到,本地DNS服務器就會向DNS的根域名服務器發起查詢請求:請問老大, www.egsec.cn 的ip是啥?
  4. 根域名服務器收到請求后,看到這是個 .cn 的域名,就回信說:這個域名是由 .cn 老弟管理的,你去問他好了,這是.cn老弟的聯繫方式(ip1)。
  5. 本地 DNS 服務器接收到回信后,照着老大哥給的聯繫方式(ip1),馬上給 .cn 這個頂級域名服務器發起請求:請問 .cn 大大,www.egsec.cn 的ip 是啥?
  6. .cn 頂級域名服務器接收到請求后,看到這是 egsec.cn 的域名,就回信說:這個域名是 .egsec.cn 老弟管理的,你就去問他就行了,這是他的聯繫方式(ip2)
  7. 本地 DNS 服務器接收到回信后,按照前輩的指引(ip2),又向 .egsec.cn 這個權威域名服務器發起請求:請問 egsec.cn 大大,請問 www.egsec.cn 的ip是啥?
  8. egsec.cn 權威域名服務器接收到請求后,確認了是自己管理的域名,馬上查了下自己的小本本,把 www.egsec.cn 的ip告訴了 本地DNS服務器。
  9. 本地DNS服務器接收到回信后,非常地開心,這下總算拿到了www.egsec.cn的ip了,馬上把這個消息告訴了要求查詢的客戶(就是你的電腦)。由於這個過程比較漫長,本地DNS服務器為了節省時間,也為了盡量不去打擾各位老大哥,就把這個查詢結果偷偷地記在了自己的小本本上,方便下次有人來查詢時,可以快速回應。

總結起來就是三句話:

  • 從”根域名服務器”查到”頂級域名服務器”的NS記錄和A記錄(IP地址)
  • 從”頂級域名服務器”查到”次級域名服務器”的NS記錄和A記錄(IP地址)
  • 從”次級域名服務器”查出”主機名”的IP地址

DNS的緩存時間

上面的幾個步驟里,可以看到有兩個地方會緩存 DNS 的查詢記錄,有了緩存,在一定程度上會提高查詢效率,但同時在準確率上會有所損失。

因此我們在配置 DNS 解析的時候,會有一個 TTL 參數(Time To Live),意思就是這個緩存可以存活多長時間,過了這個時間,本地 DNS 就會刪除這條記錄,刪除了緩存后,你再訪問,就要重新走一遍上面的流程,獲取最新的地址。

DNS 的記錄類型

當我們在阿里雲買了一個域名后,可以配置我們主機域名解析規則,也就是 記錄。  

阿里雲域名雲解析(不管是哪個服務商都一樣):

常見的 DNS 記錄類型如下

  • A:地址記錄(Address),返回域名指向的IP地址。
  • NS:域名服務器記錄(Name Server),返回保存下一級域名信息的服務器地址。該記錄只能設置為域名,不能設置為IP地址。
  • MX:郵件記錄(Mail eXchange),返回接收电子郵件的服務器地址。
  • CNAME:規範名稱記錄(Canonical Name),返回另一個域名,即當前查詢的域名是另一個域名的跳轉,詳見下文。
  • PTR:逆向查詢記錄(Pointer Record),只用於從IP地址查詢域名,詳見下文。

DNS報文結構

  1. 事務 ID:DNS 報文的 ID 標識。對於請求報文和其對應的應答報文,該字段的值是相同的。通過它可以區分 DNS 應答報文是對哪個請求進行響應的。
  2. 標誌:DNS 報文中的標誌字段。
  3. 問題計數:DNS 查詢請求的數目。
  4. 回答資源記錄數:DNS 響應的數目。
  5. 權威名稱服務器計數:權威名稱服務器的數目。
  6. 附加資源記錄數:額外的記錄數目(權威名稱服務器對應 IP 地址的數目)

DNS劫持與HTTP劫持

通過上面的講解,我們都知道了,DNS 完成了一次域名到 IP 的映射查詢,當你在訪問 www.egsec.cn 時,能正確返回給你 我網站首頁的 ip。

但如果此時 DNS 解析出現了一些問題,當你想要訪問 www.egsec.cn 時,卻返回給你 www.baidu.com 的ip,這就是我們常說的 DNS 劫持。

與之容易混淆的有 HTTP 劫持。

什麼是 HTTP 劫持?

你一定見過當你在訪問 某個網站時,右下角也突然彈出了一個扎眼的廣告彈窗。這就是 HTTP 劫持。

藉助別人文章里的例子,它們倆的區別就好比是

  • DNS劫持是你想去機場的時候,把你給丟到火車站。
  • HTTP劫持是你去機場途中,有人給你塞小廣告。

DNS劫持 是如何產生的?

下面大概說幾種DNS劫持方法:

1.本機DNS劫持

攻擊者通過某些手段使用戶的計算機感染上木馬病毒,或者惡意軟件之後,惡意修改本地DNS配置,比如修改本地hosts文件,緩存等

2. 路由DNS劫持

很多用戶默認路由器的默認密碼,攻擊者可以侵入到路由管理員賬號中,修改路由器的默認配置

3.攻擊DNS服務器

直接攻擊DNS服務器,例如對DNS服務器進行DDOS攻擊,可以是DNS服務器宕機,出現異常請求,還可以利用某些手段感染dns服務器的緩存,使給用戶返回來的是惡意的ip地址

如何在本地查詢 DNS 解析結果?

nslookup命令:

命令格式:nslookup [查詢的域名] [指定DNS服務器]

你也可以指定公網的域名服務器進行查詢,比如常見的 114.114.114.114

手動清理DNS緩存

MacOS:

sudo dscacheutil -flushcache
$ sudo killall -HUP mDNSResponder

Windows:

$ ipconfig /flushdns

Linux:

使用NSCD的DNS緩存
$ sudo /etc/init.d/nscd restart

# 服務器或者路由器使用DNSMASQ
$ sudo dnsmasq restart

  

DNS詳解篇完

轉發請註明出處(EG Blog:blog.egsec.cn),謝謝!

 

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

【其他文章推薦】

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

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

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

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

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

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

落實低碳城市 荷蘭阿姆斯特丹機場提供百餘輛 Tesla 租賃

  近日美國電動車廠 Tesla 宣布與荷蘭當地租車公司合作,提供阿姆斯特丹 Schiphol 機場旅客 Model S 租車方案。   對於素有「腳踏車烏托邦」美名之稱的荷蘭而言,出門不開車不是一個選項,而是一個自然不過的習慣,甚至推行各項自然發電方式,其中阿姆斯特丹更是打造成低碳城市,在政府的綠能政策下,電動的推行早已行之有年。   而這次由荷蘭 BBF Schipholtaxi 與 BIOS-groep 兩大租車公司通力合作,一口氣導入 167 輛特斯拉 Model S 加入汽車租賃,以首都阿姆斯特丹主要機場史基浦(Schiphol)國際機場作為出租據點,鎖定國際旅客與國內高端客群,也替低碳城市計畫盡一份心力。     (Source:)  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

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

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

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

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

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

拯救漏油生態危機:菲律賓吉馬拉斯島的故事

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

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

【其他文章推薦】

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

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

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

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

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

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