{"id":244,"date":"2022-09-19T21:23:35","date_gmt":"2022-09-19T20:23:35","guid":{"rendered":"https:\/\/blog.jeronimodiaz.com\/en\/configurar-el-servidor-de-metricas-de-kubernetes-en-modo-seguro\/"},"modified":"2025-07-05T22:08:57","modified_gmt":"2025-07-05T21:08:57","slug":"configurar-el-servidor-de-metricas-de-kubernetes-en-modo-seguro","status":"publish","type":"post","link":"https:\/\/blog.jeronimodiaz.com\/es\/configurar-el-servidor-de-metricas-de-kubernetes-en-modo-seguro\/","title":{"rendered":"Configurar el servidor de m\u00e9tricas de Kubernetes en modo seguro"},"content":{"rendered":"\n<p>Despu\u00e9s de varias horas investigando por qu\u00e9 el componente metrics-server que se ejecuta en mi cl\u00faster de kubernetes obten\u00eda errores relacionados con un certificado no v\u00e1lido al recuperar m\u00e9tricas de los nodos, he podido solucionar el problema y obtener m\u00e9tricas correctamente de todos los nodos kubernetes mediante HTTPS.<\/p>\n\n\n\n<p>En las l\u00edneas siguientes se describe cu\u00e1l es el problema y c\u00f3mo solucionarlo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Problema<\/h2>\n\n\n\n<p>Despu\u00e9s de desplegar el componente metrics-server, el pod metrics-server no es capaz de arrancar. Veo muchos mensajes como el de las l\u00edneas siguientes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>E1229 07:09:05.013998 1 summary.go:97] error while getting metrics summary from Kubelet node2(192.168.x.x:10250): Get https:\/\/192.168.x.x:10250\/metrics\/resource\/: x509: cannot validate certificate for 192.168.x.x because it doesn't contain any IP SANs<\/code><\/pre>\n\n\n\n<p>El mensaje de error es muy claro. El problema es que el certificado configurado en los nodos del cl\u00faster de kubernetes no permite IPs como nombres de host en la URL de consulta de m\u00e9tricas.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Soluci\u00f3n<\/h2>\n\n\n\n<p>Gracias a Github, he encontrado una soluci\u00f3n que funcionaba en el momento en que se plante\u00f3 el problema, pero que hoy en d\u00eda no funciona.<\/p>\n\n\n\n<p>De todas formas, tras unos peque\u00f1os retoques, consigo que funcione en Kubernetes 1.23<\/p>\n\n\n\n<p>En mi caso, estoy utilizando un portatil corriendo Ubuntu por lo que los siguientes pasos son los que he ejecutado en Ubuntu.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Instalar los siguientes paquetes necesarios para los siguientes pasos<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install -y golang-cfssl jq<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Generar una Solicitud de Firma de Certificado (CSR) . Tras ejecutar el siguiente comando, se crear\u00e1n dos nuevos archivos <em>kubelet-server-key<\/em> <em>.pem<\/em> y <em>kubelet-server.csr<\/em> <\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n    \"hosts\": &#91;\n        \"master1\",\n        \"node2\",\n        \"node3\",\n        \"node4\",\n        \"192.168.30.12\",\n        \"192.168.30.11\",\n        \"192.168.30.15\",\n        \"192.168.30.16\"\n    ],\n    \"CN\": \"system:node:kubelet-server\",\n    \"name\": &#91;\n        {\n            \"C\": \"ES\",\n            \"ST\": \"Spain\",\n            \"L\": \"Malaga\",\n            \"O\": \"system:nodes\",\n            \"OU\": \"system:nodes\"\n        }\n    ]\n}<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Es hora de crear el CSR en el cluster de kubernetes para que kubernetes pueda crear el certificado correcto  <\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &lt;&lt;EOF | kubectl create -f -\napiVersion: certificates.k8s.io\/v1\nkind: CertificateSigningRequest \nmetadata:\n  name: kubelet-server\nspec:\n  request: $(cat kubelet-server.csr | base64 | tr -d '\\n')\n  signerName: kubernetes.io\/kubelet-serving\n  groups:\n  - system:nodes\n  - system:authenticated\n  usages:\n  - digital signature\n  - key encipherment\n  - server auth\nEOF<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Despu\u00e9s de crear el CSR en kubernetes, necesitamos aprobarlo  <\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl certificate approve kubelet-server<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Descargar el nuevo certificado<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get csr kubelet-server -o jsonpath='{.status.certificate}' | base64 --decode &gt; kubelet-server.pem<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Llegados a este punto, deber\u00edamos tener dos archivos diferentes que contienen la clave privada<em>(<\/em><em>kubelet-server-key<\/em><em>.pem<\/em>) y la clave p\u00fablica<em>(kubelet-server.pem<\/em>) del certificado. Necesitamos copiar estos dos archivos en todos los nodos de kubernetes (masters y workers). He decidido colocar estos archivos en <em>\/var\/lib\/kubernetes\/pki<\/em>, por lo que los archivos deben ubicarse en <em>\/var\/lib\/kubernetes\/pki\/kubelet-server-key.pem<\/em> y <em>\/var\/lib\/kubernetes\/pki\/kubelet-server.pem<\/em><\/li>\n\n\n\n<li>Debemos configurar kubelet para que lea los archivos que acabamos de copiar en todos los nodos de kubernetes. Necesitamos saber qu\u00e9 archivo utiliza el componente kubelet para cargar la configuraci\u00f3n<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ps aux | grep kubelet<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>La salida del comando anterior deber\u00eda tener un aspecto similar al de las siguientes l\u00edneas<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>root 2020195 5.6 0.3 2160136 121488 ? Ssl Sep18 73:58 \/opt\/bin\/kubelet --logtostderr=true --v=2 --node-ip=192.168.30.16 --hostname-override=node4\n--bootstrap-kubeconfig=\/etc\/kubernetes\/bootstrap-kubelet.conf --config=\/etc\/kubernetes\/kubelet-config.yaml --kubeconfig=\/etc\/kubernetes\/kubelet.conf\n--container-runtime=remote --container-runtime-endpoint=unix:\/\/\/var\/run\/containerd\/containerd.sock --runtime-cgroups=\/systemd\/system.slice --network-plugin=cni --cni-conf-dir=\/etc\/cni\/net.d\n--cni-bin-dir=\/opt\/cni\/bin --volume-plugin-dir=\/var\/lib\/kubelet\/volumeplugins<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Podemos comprobar que el archivo de configuraci\u00f3n que lee kubelet es <em>\/etc\/kubernetes\/kubelet-config.yaml<\/em><br>Tenemos que editar este archivo para configurar d\u00f3nde se encuentran las partes privada y p\u00fablica de los certificados. Ten en cuenta que los siguientes comandos deben ejecutarse como usuario root. <\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>echo \"tlsPrivateKeyFile: \/var\/lib\/kubelet\/pki\/kubelet-server-key.pem\" &gt;&gt; \/etc\/kubernetes\/kubelet-config.yaml\necho \"tlsCertFile: \/var\/lib\/kubelet\/pki\/kubelet-server.pem\" &gt;&gt; \/etc\/kubernetes\/kubelet-config.yaml<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>El \u00faltimo paso es reiniciar kubelet en todos los nodos  <\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl daemon-reload\nsudo systemctl restart kubelet<\/code><\/pre>\n\n\n\n<p>En este punto, kubelet deber\u00eda estar utilizando un certificado que contenga las IPs de todos los nodos de kubernetes y que haya sido firmado por la CA del cl\u00faster para que el servidor de m\u00e9tricas pueda obtener todas las m\u00e9tricas utilizando HTTPS.<\/p>\n\n\n\n<p>Espero que este post te resulte \u00fatil y que puedas solucionar este problema f\u00e1cilmente si lo encuentras.<\/p>\n\n\n\n<p>\u00a1Nos vemos en el pr\u00f3ximo post!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Despu\u00e9s de varias horas investigando por qu\u00e9 el componente metrics-server que se ejecuta en mi cl\u00faster de kubernetes obten\u00eda errores relacionados con un certificado no v\u00e1lido al recuperar m\u00e9tricas de&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[104],"tags":[105,107,106],"class_list":["post-244","post","type-post","status-publish","format-standard","hentry","category-kubernetes-es","tag-kubernetes-es","tag-metricas","tag-servidor-es"],"_links":{"self":[{"href":"https:\/\/blog.jeronimodiaz.com\/es\/wp-json\/wp\/v2\/posts\/244","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.jeronimodiaz.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.jeronimodiaz.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jeronimodiaz.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jeronimodiaz.com\/es\/wp-json\/wp\/v2\/comments?post=244"}],"version-history":[{"count":3,"href":"https:\/\/blog.jeronimodiaz.com\/es\/wp-json\/wp\/v2\/posts\/244\/revisions"}],"predecessor-version":[{"id":309,"href":"https:\/\/blog.jeronimodiaz.com\/es\/wp-json\/wp\/v2\/posts\/244\/revisions\/309"}],"wp:attachment":[{"href":"https:\/\/blog.jeronimodiaz.com\/es\/wp-json\/wp\/v2\/media?parent=244"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jeronimodiaz.com\/es\/wp-json\/wp\/v2\/categories?post=244"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jeronimodiaz.com\/es\/wp-json\/wp\/v2\/tags?post=244"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}