Como instalar o Kubernetes no Ubuntu 18?

Aprenda a instalar o Kubernetes no Ubuntu.


Kubernetes é uma ferramenta de orquestração de contêiner de código aberto desenvolvida pelo Google. Neste artigo, você aprenderá como configurar o Kubernetes com um nó mestre e um nó trabalhador. Verifique se o Docker está instalado nos nós principal e de trabalho.

Detalhes e configuração do ambiente

Para a demonstração, eu tenho 2 sistemas Ubuntu, um será o nó mestre e o outro será o nó do trabalhador. A configuração do servidor é a seguinte.

  • 2 CPUs
  • Mestre – 4 GB de RAM / Trabalhador – 2 GB de RAM
  • Disco rígido de 10 GB

Use o comando hostnamectl para definir o nome do host nos dois sistemas.

No nó principal:

[protegido por email]: ~ $ sudo hostnamectl set-hostname kubernetes-master

No nó do trabalhador:

[protegido por email]: ~ $ sudo hostnamectl set-hostname kubernetes-worker

Então, abaixo estão os detalhes dos dois nós.

Nó Mestre

  • Nome do host: kubernetes-master
  • Endereço IP: 192.168.0.107

Nó de trabalhador

  • Nome do host: kubernetes-worker
  • Endereço IP: 192.168.0.108

Edite o arquivo hosts nos dois sistemas.

[protegido por email]: ~ $ sudo gedit / etc / hosts

192.168.0.107 kubernetes-master
192.168.0.109 kubernetes-worker

Antes de começar a instalar o Kubernetes, execute o comando abaixo nos nós mestre e trabalhador para verificar se o Docker está instalado e em execução.

[protegido por email]: ~ $ estado do docker de serviço sudo
senha [sudo] para geekflare:
● docker.service – Docker Application Container Engine
Carregado: carregado (/lib/systemd/system/docker.service; ativado; predefinição de fornecedor: ativado)
Ativo: ativo (em execução) desde Sáb 2019-11-23 15:39:36 EST; 3 semanas 0 dias atrás
Documentos: https://docs.docker.com
PID principal: 8840 (dockerd)
Tarefas: 17
Memória: 42.3M
CGroup: /system.slice/docker.service
88─8840 / usr / bin / dockerd -H fd: // –containerd = / run / containserd / containserd.sock

23 de novembro 15:39:35 geekflare dockerd [8840]: time ="O que você precisa saber para começar o dia bem-informado" level = aviso msg ="Seu kernel não suporta cgrou
23 de novembro 15:39:35 geekflare dockerd [8840]: time ="2019-11-23T15: 39: 35.093149218-05: 00" level = info msg ="Carregando contêineres: início."
23 de novembro 15:39:35 geekflare dockerd [8840]: time ="Por que você está reportando essa página?" level = info msg ="Ponte padrão (docker0) é atribuída
23 de novembro 15:39:36 geekflare dockerd [8840]: time ="2019-11-23T15: 39: 36.078753190-05: 00" level = info msg ="Carregando contêineres: pronto."
23 de novembro 15:39:36 geekflare dockerd [8840]: time ="O que você precisa saber para começar o dia bem-informado" level = info msg ="Daemon do Docker" commit = 481bc77 graphdr
23 de novembro 15:39:36 geekflare dockerd [8840]: time ="Por que você está reportando essa página?" level = error msg ="cluster encerrado com erro: error whi
23 de novembro 15:39:36 geekflare dockerd [8840]: time ="O que você precisa saber para começar o dia bem-informado" level = error msg ="não foi possível iniciar o componente enxame
23 de novembro 15:39:36 geekflare dockerd [8840]: time ="Por que você está reportando essa página?" level = info msg ="Daemon concluiu a inicialização"
Nov 23 15:39:36 geekflare systemd [1]: Iniciado o Docker Application Container Engine.
23 de novembro 15:39:36 geekflare dockerd [8840]: time ="Por que você está reportando essa página?" level = info msg ="Escuta da API em /home/geekflare/docker.sock
linhas 1-20 / 20 (END)

Instale o Kubernetes

Execute todos os comandos mencionados nesta seção nos nós principais e nos trabalhadores.

Primeiro, adicione a chave do repositório do pacote Kubernetes.

[protegido por email]: ~ $ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add
senha [sudo] para geekflare:
Está bem

Execute o comando abaixo para configurar o repositório de pacotes Kubernetes.

[protegido por email]: ~ $ sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"
Hit: 1 https://download.docker.com/linux/ubuntu bionic InRelease
Hit: 2 http://ppa.launchpad.net/ansible/ansible/ubuntu cosmic InRelease
Get: 3 http://apt.puppetlabs.com InRelease biônico [85,3 kB]
Hit: 5 http://security.ubuntu.com/ubuntu cosmic-security InRelease
Hit: 6 http://us.archive.ubuntu.com/ubuntu cosmic InRelease
Ign: 7 http://pkg.jenkins.io/debian-stable binário / InRelease
Hit: 8 http://us.archive.ubuntu.com/ubuntu cosmic-updates InRelease
Hit: 9 http://pkg.jenkins.io/debian-stable binário / Versão
Hit: 10 http://us.archive.ubuntu.com/ubuntu cosmic-backports InRelease
Get: 4 https://packages.cloud.google.com/apt kubernetes-xenial InRelease [8,993 B]
Get: 11 http://apt.puppetlabs.com pacotes bionic / puppet6 amd64 [36,1 kB]
Get: 13 https://packages.cloud.google.com/apt kubernetes-xenial / main amd64 pacotes [32,2 kB]
Recuperado 163 kB em 3s (49,1 kB / s)
Lendo listas de pacotes … Concluído

Antes de prosseguir, desative a troca nos dois nós.

[protegido por email]: ~ $ sudo swapoff -a

Instale o Kubeadm

Agora você precisa instalar o kubeadm.

kubeadm é uma ferramenta no Kubernetes que é usada para adicionar nós no cluster Kubernetes.

[protegido por email]: ~ $ sudo apt-get install kubeadm -y
Lendo listas de pacotes … Concluído
Construindo árvore de dependência
Lendo informações do estado … Concluído
Os seguintes pacotes adicionais serão instalados:
conntrack cri-tools ebtables ethtool kubectl kubelet kubernetes-cni socat
Os seguintes NOVOS pacotes serão instalados:
conntrack cri-tools ebtables ethtool kubeadm kubectl kubelet kubernetes-cni socat
0 atualizado, 9 recém-instalado, 0 para remover e 235 não atualizado.
Precisa obter 51,8 MB de arquivos.
Após esta operação, 273 MB de espaço em disco adicional serão usados.
Get: 3 http://us.archive.ubuntu.com/ubuntu cosmic / main amd64 conntrack amd64 1: 1.4.5-1 [30.2 kB]
Obtenha: 1 https://packages.cloud.google.com/apt kubernetes-xenial / main amd64 cri-ferramentas amd64 1.13.0-00 [8.776 kB]
Get: 6 http://us.archive.ubuntu.com/ubuntu cosmic / main amd64 ebtables amd64 2.0.10.4-3.5ubuntu5 [79.8 kB]
Get: 8 http://us.archive.ubuntu.com/ubuntu cosmic / main amd64 ethtool amd64 1: 4.16-1 [115 kB]
Get: 9 http://us.archive.ubuntu.com/ubuntu cosmic / main amd64 socat amd64 1.7.3.2-2ubuntu2 [342 kB]
Get: 2 https://packages.cloud.google.com/apt kubernetes-xenial / amd64 principal kubernetes-cni amd64 0.7.5-00 [6.473 kB]
Obtenha: 4 https://packages.cloud.google.com/apt kubernetes-xenial / amd64 principal kubelet amd64 1.17.0-00 [19.2 MB]
Get: 5 https://packages.cloud.google.com/apt kubernetes-xenial / main amd64 kubectl amd64 1.17.0-00 [8.742 kB]
Get: 7 https://packages.cloud.google.com/apt kubernetes-xenial / main amd64 kubeadm amd64 1.17.0-00 [8.059 kB]
Obtido 51,8 MB em 8s (6.419 kB / s)
Selecionando conntrack de pacote anteriormente não selecionado.
(Lendo arquivos e diretórios do banco de dados … 318151 atualmente instalados.)
Preparando para descompactar … / 0-conntrack_1% 3a1.4.5-1_amd64.deb …
Descompactando conntrack (1: 1.4.5-1) …
Selecionando cri-tools de pacotes anteriormente não selecionadas.
Preparando para descompactar … / 1-cri-tools_1.13.0-00_amd64.deb …
Desembalando cri-tools (1.13.0-00) …
Selecionando ebtables de pacotes não selecionados anteriormente.
Preparando para descompactar … / 2-ebtables_2.0.10.4-3.5ubuntu5_amd64.deb …
Descompactando ebtables (2.0.10.4-3.5ubuntu5) …
Selecionando o pacote ethtool anteriormente não selecionado.
Preparando para descompactar … / 3-ethtool_1% 3a4.16-1_amd64.deb …
Como desembalar o ettool (1: 4.16-1) …
Selecionando o pacote kubernetes-cni anteriormente não selecionado.
Preparando para descompactar … / 4-kubernetes-cni_0.7.5-00_amd64.deb …
Descompactando kubernetes-cni (0.7.5-00) …
Selecionando socat anteriormente não selecionado do pacote.
Preparando para descompactar … / 5-socat_1.7.3.2-2ubuntu2_amd64.deb …
Descompactando o socat (1.7.3.2-2ubuntu2) …
Selecionando o kubelet de pacote anteriormente não selecionado.
Preparando para descompactar … / 6-kubelet_1.17.0-00_amd64.deb …
Descompactando o kubelet (1.17.0-00) …
Selecionando o pacote não selecionado anteriormente kubectl.
Preparando para descompactar … / 7-kubectl_1.17.0-00_amd64.deb …
Descompactando o kubectl (1.17.0-00) …
Selecionando o pacote não selecionado anteriormente kubeadm.
Preparando para descompactar … / 8-kubeadm_1.17.0-00_amd64.deb …
Descompactando o kubeadm (1.17.0-00) …
Configurando o conntrack (1: 1.4.5-1) …
Configurando o kubernetes-cni (0.7.5-00) …
Configurando cri-tools (1.13.0-00) …
Configurando o socat (1.7.3.2-2ubuntu2) …
Processando gatilhos para systemd (239-7ubuntu10.12) …
Configurando o ebtables (2.0.10.4-3.5ubuntu5) …
Link simbólico criado /etc/systemd/system/multi-user.target.wants/ebtables.service → /lib/systemd/system/ebtables.service.
update-rc.d: warning: ações de início e parada não são mais suportadas; voltando aos padrões
Configurando o kubectl (1.17.0-00) …
Processando gatilhos para man-db (2.8.4-2) …
Configurando o ethtool (1: 4.16-1) …
Configurando o kubelet (1.17.0-00) …
Link simbólico criado /etc/systemd/system/multi-user.target.wants/kubelet.service → /lib/systemd/system/kubelet.service.
Configurando o kubeadm (1.17.0-00) …
Processando gatilhos para systemd (239-7ubuntu10.12) …

Verifique a versão do kubeadm para verificar se foi instalada corretamente.

[protegido por email]: ~ $ versão do kubeadm
Versão do kubeadm: &version.Info {Major:"1", Menor:"17", GitVersion:"v1.17.0", GitCommit:"70132b0f130acc0bed193d9ba59dd186f0e634cf", GitTreeState:"limpar \ limpo", Data de construção:"2019-12-07T21: 17: 50Z", GoVersion:"go1.13.4", Compilador:"gc", Plataforma:"linux / amd64"}

Inicializar cluster do Kubernetes

Agora, execute o comando init para inicializar o cluster Kubernetes apenas no diretório nó principal. Use –apiserver-advertise-address para informar o nó do trabalhador sobre o endereço IP do mestre.

[protegido por email]: ~ $ sudo kubeadm init –apiserver-advertise-address = 192.168.0.107 –pod-network-cidr = 10.244.0.0 / 16
W1217 11: 05: 15.474854 10193 validation.go: 28] Não é possível validar a configuração do kube-proxy – nenhum validador está disponível
W1217 11: 05: 15.474935 10193 validation.go: 28] Não é possível validar a configuração do kubelet – nenhum validador está disponível
[init] Usando a versão do Kubernetes: v1.17.0
[preflight] Executando verificações antes do voo
[AVISO IsDockerSystemdCheck]: detectado "cgroupfs" como o driver cgroup do Docker. O driver recomendado é "systemd". Siga o guia em https://kubernetes.io/docs/setup/cri/
[preflight] Obtendo imagens necessárias para configurar um cluster Kubernetes
[preflight] Isso pode levar um ou dois minutos, dependendo da velocidade da sua conexão com a internet
[preflight] Você também pode executar esta ação com antecedência usando ‘kubeadm config images pull’
[kubelet-start] Escrevendo arquivo de ambiente kubelet com sinalizadores para arquivo "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Escrevendo a configuração do kubelet no arquivo "/var/lib/kubelet/config.yaml"
[kubelet-start] Iniciando o kubelet
[certs] Usando a pasta certificateDir "/ etc / kubernetes / pki"
[certs] Gerando "ca" certificado e chave
[certs] Gerando "apiserver" certificado e chave
[certs] apiserver que serve cert é assinado para nomes DNS [kubernetes-master kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] e IPs [10.96.0.1 192.168.0.107]
[certs] Gerando "apiserver-kubelet-client" certificado e chave
[certs] Gerando "front-proxy-ca" certificado e chave
[certs] Gerando "cliente de proxy frontal" certificado e chave
[certs] Gerando "etcd / ca" certificado e chave
[certs] Gerando "etcd / server" certificado e chave
[certs] etcd / server serv cert é assinado para nomes DNS [kubernetes-master localhost] e IPs [192.168.0.107 127.0.0.1 :: 1]
[certs] Gerando "etcd / par" certificado e chave
[certs] etcd / peer serv cert é assinado para nomes DNS [kubernetes-master localhost] e IPs [192.168.0.107 127.0.0.1 :: 1]
[certs] Gerando "etcd / healthcheck-client" certificado e chave
[certs] Gerando "apiserver-etcd-client" certificado e chave
[certs] Gerando "sa" chave e chave pública
[kubeconfig] Usando a pasta kubeconfig "/ etc / kubernetes"
[kubeconfig] Escrevendo "admin.conf" arquivo kubeconfig
[kubeconfig] Escrevendo "kubelet.conf" arquivo kubeconfig
[kubeconfig] Escrevendo "controller-manager.conf" arquivo kubeconfig
[kubeconfig] Escrevendo "scheduler.conf" arquivo kubeconfig
[plano de controle] Usando pasta de manifesto "/ etc / kubernetes / manifestos"
[plano de controle] Criando manifesto de Pod estático para "kube-apiserver"
[plano de controle] Criando manifesto de Pod estático para "kube-controller-manager"
W1217 11: 05: 25.584769 10193 manifestests.go: 214] o modo de autorização padrão do kube-apiserver é "Nó, RBAC"; usando "Nó, RBAC"
[plano de controle] Criando manifesto de Pod estático para "kube-scheduler"
W1217 11: 05: 25.587128 10193 manifestests.go: 214] o modo de autorização padrão do kube-apiserver é "Nó, RBAC"; usando "Nó, RBAC"
[etcd] Criando manifesto de Pod estático para etcd local em "/ etc / kubernetes / manifestos"
[wait-control-plane] Aguardando o kubelet inicializar o plano de controle como Pods estáticos do diretório "/ etc / kubernetes / manifestos". Isso pode levar até 4m0s
[apiclient] Todos os componentes do plano de controle ficam saudáveis ​​após 35.010368 segundos
[upload-config] Armazenando a configuração usada no ConfigMap "kubeadm-config" no "sistema kube" Namespace
[kubelet] Criando um ConfigMap "kubelet-config-1.17" no espaço de nomes kube-system com a configuração para os kubelets no cluster
[upload-certs] Ignorando a fase. Por favor, veja –upload-certs
[mark-control-plane] Marcando o nó kubernetes-master como plano de controle adicionando o rótulo "node-role.kubernetes.io/master= ”"
[mark-control-plane] Marcando o nó kubernetes-master como plano de controle, adicionando as manchas [node-role.kubernetes.io/master:NoSchedule]
[token de inicialização] Usando o token: dmamk9.0nmo62mhom8961qw
[token de bootstrap] Configurando tokens de bootstrap, informações do cluster, ConfigMap, funções RBAC
[bootstrap-token] configurou regras RBAC para permitir que os tokens de Nó Bootstrap publiquem CSRs para que os nós obtenham credenciais de certificado de longo prazo
As regras RBAC configuradas pelo [bootstrap-token] para permitir que o controlador csrapprover aprove automaticamente CSRs a partir de um token de bootstrap do nó
[bootstrap-token] configurou regras RBAC para permitir a rotação de certificados para todos os certificados de cliente do nó no cluster
[bootstrap-token] Criando o "informações do cluster" ConfigMap no "kube-public" namespace
[kubelet-finalize] Atualizando "/etc/kubernetes/kubelet.conf" para apontar para um certificado e uma chave rotativos do cliente kubelet
[addons] Complemento essencial aplicado: CoreDNS
[addons] Complemento essencial aplicado: kube-proxy

Seu plano de controle Kubernetes foi inicializado com sucesso!

Para começar a usar seu cluster, você precisa executar o seguinte como um usuário comum:

mkdir -p $ HOME / .kube
sudo cp -i /etc/kubernetes/admin.conf $ HOME / .kube / config
sudo chown $ (id -u): $ (id -g) $ HOME / .kube / config

Em seguida, você precisa implantar uma rede de pod no cluster.

Execute o kubectl apply -f [podnetwork] .yaml com uma das opções listadas em https://kubernetes.io/docs/concepts/cluster-administration/addons/

Em seguida, você pode ingressar em qualquer número de nós do trabalhador executando o seguinte em cada um como root:

junção do kubeadm 192.168.0.107:6443 –token dmamk9.0nmo62mhom8961qw –discovery-token-ca-cert-hash sha256: 2de92f42e84d2020d8b19b1778785df5f8196e5eedaa5664ad911e8c23f58963

Conforme mencionado na saída acima, crie o diretório .kube e copie o arquivo admin.conf para o arquivo de configuração no diretório .kube.

[protegido por email]: ~ $ mkdir -p $ HOME / .kube
[protegido por email]: ~ $ sudo cp -i /etc/kubernetes/admin.conf $ HOME / .kube / config
[protegido por email]: ~ $ sudo chown $ (id -u): $ (id -g) $ HOME / .kube / config

Nesse momento, quando você executa o comando kubectl get nodes, verá que o status do nó principal é NotReady.

[protegido por email]: ~ $ sudo kubectl obtém nós
NOME ESTADO PAPÉIS VERSÃO IDADE
kubernetes-master NotReady master 2m34s v1.17.0

Implantar rede de pods – Flanela

Em seguida, você precisa implantar uma rede de pod no nó principal. Estou usando a rede de pods de flanela. É usado para se comunicar entre nós no cluster Kubernetes.

[protegido por email]: ~ $ sudo kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
podsecuritypolicy.policy / psp.flannel.unprivileged created
clusterrole.rbac.authorization.k8s.io/flannel criado
clusterrolebinding.rbac.authorization.k8s.io/flannel created
conta de serviço / flanela criada
configmap / kube-flannel-cfg criado
daemonset.apps / kube-flannel-ds-amd64 criado
daemonset.apps / kube-flannel-ds-arm64 criado
daemonset.apps / kube-flannel-ds-arm criado
daemonset.apps / kube-flannel-ds-ppc64le criado
daemonset.apps / kube-flannel-ds-s390x criado

Verifique o status do nó principal, ele deve estar no estado Pronto.

[protegido por email]: ~ $ sudo kubectl obtém nós
NOME ESTADO PAPÉIS VERSÃO IDADE
kubernetes-master Ready master 4m41s v1.17.0

Após alguns segundos, verifique se todos os pods estão em funcionamento.

[protegido por email]: ~ $ kubectl get pods –all-namespaces
NAMESPACE NOME PRONTO ESTADO RESTARTS IDADE
kube-system coredns-6955765f44-rzw9d 1/1 Execução 0 4m17s
kube-system coredns-6955765f44-xvgdp 1/1 Executando 0 4m17s
kube-system etcd-kubernetes-master 1/1 Executando 0 4m27s
kube-system kube-apiserver-kubernetes-master 1/1 Rodando 0 4m27s
kube-system kube-controller-manager-kubernetes-master 1/1 Executando 0 4m27s
kube-system kube-flannel-ds-amd64-c2rf5 1/1 Executando 0 81s
kube-system kube-proxy-mvdd7 1/1 Executando 0 4m17s
kube-system kube-scheduler-kubernetes-master 1/1 Executando 0 4m27s

Adicionar nó de trabalho ao cluster

Agora que seu nó mestre está configurado e funcionando corretamente, é hora de adicionar o nó do trabalhador. Aqui, você precisa executar o comando join no nó do trabalhador, obtido após a inicialização do kubeadm.

Execute o comando abaixo no nó do trabalhador para ingressar no nó principal.

[protegido por email]: ~ $ sudo kubeadm join 192.168.0.107:6443 –token dmamk9.0nmo62mhom8961qw –discovery-token-ca-cert-hash sha256: 2de92f42e84d2020d8b19b1778785df5f8196e5eedaa5664ad911e63c23
senha [sudo] para geekflare:
W1217 11: 08: 01.066191 28968 join.go: 346] [preflight] AVISO: As configurações de JoinControlPane.controlPlane serão ignoradas quando o sinalizador do plano de controle não estiver definido.
[preflight] Executando verificações antes do voo
[AVISO IsDockerSystemdCheck]: detectado "cgroupfs" como o driver cgroup do Docker. O driver recomendado é "systemd". Siga o guia em https://kubernetes.io/docs/setup/cri/
[preflight] Lendo a configuração do cluster…
[preflight] FYI: Você pode ver este arquivo de configuração com ‘kubectl -n kube-system get cm kubeadm-config -oyaml’
[kubelet-start] Fazendo o download da configuração para o kubelet a partir do "kubelet-config-1.17" ConfigMap no espaço para nome do sistema kube
[kubelet-start] Escrevendo a configuração do kubelet no arquivo "/var/lib/kubelet/config.yaml"
[kubelet-start] Escrevendo arquivo de ambiente kubelet com sinalizadores para arquivo "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Iniciando o kubelet
[kubelet-start] Aguardando o kubelet executar o TLS Bootstrap…

Este nó ingressou no cluster:
* A solicitação de assinatura de certificado foi enviada ao apiserver e uma resposta foi recebida.
* O Kubelet foi informado dos novos detalhes da conexão segura.

Execute ‘kubectl get nodes’ no plano de controle para ver esse nó ingressar no cluster.

No nó principal:

Você verá mais alguns pods em execução agora após o nó do trabalhador ingressar no cluster.

[protegido por email]: ~ $ kubectl get pods –all-namespaces
NAMESPACE NOME PRONTO ESTADO RESTARTS IDADE
kube-system coredns-6955765f44-9c7jc 1/1 Rodando 0 5m3s
kube-system coredns-6955765f44-c9s9r 1/1 Executando 0 5m3s
kube-system etcd-kubernetes-master 1/1 Executando 0 5m12s
kube-system kube-apiserver-kubernetes-master 1/1 Executando 0 5m12s
kube-system kube-controller-manager-kubernetes-master 1/1 Executando 0 5m13s
kube-system kube-flannel-ds-amd64-lgr62 1/1 Executando 0 3m35s
kube-system kube-flannel-ds-amd64-n6vwm 1/1 Executando 0 27s
kube-system kube-proxy-9mqp6 1/1 Executando 0 27s
kube-system kube-proxy-kwkz2 1/1 Executando 0 5m3s
kube-system kube-scheduler-kubernetes-master 1/1 Executando 0 5m13s

Agora, execute o comando kubectl novamente no nó mestre para verificar se o nó do trabalhador ingressou no cluster e está em execução no estado Pronto.

[protegido por email]: ~ $ kubectl obtém nós
NOME ESTADO PAPÉIS VERSÃO IDADE
kubernetes-master Ready master 5m27s v1.17.0
kubernetes-worker Ready 31s v1.17.0

Conclusão

Agora que a instalação do Kubernetes está pronta, você pode começar a orquestrar contêineres no cluster Kubernetes. Se o Kubernetes te excita, você pode aprender aprendendo Curso Udemy.

TAG:

  • Docker

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map