kubernetes - logs - kubectl scale
¿Cómo accedo a la API de Kubernetes desde un contenedor de pod? (11)
Solía ser capaz de rizarme
https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1beta3/namespaces/default/
como mi URL base, pero en kubernetes 0.18.0 me da "no autorizado".
Lo extraño es que si utilizo la dirección IP externa de la máquina API (
http://172.17.8.101:8080/api/v1beta3/namespaces/default/
), funciona bien.
Cada pod tiene una cuenta de servicio aplicada automáticamente que le permite acceder al servidor.
La cuenta de servicio proporciona las credenciales del cliente, en forma de un token de portador, y el certificado de autoridad de certificación que se utilizó para firmar el certificado presentado por el servidor.
Con estos dos datos, puede crear una conexión segura y autenticada al dispositivo sin usar
curl -k
(también conocido como
curl --insecure
):
curl -v --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://kubernetes.default.svc/
Con RBAC habilitado, la cuenta de servicio predeterminada no tiene ningún permiso.
Mejor cree una cuenta de servicio separada para sus necesidades y úsela para crear su pod.
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: fabric8-rbac
subjects:
- kind: ServiceAccount
# Reference to upper''s `metadata.name`
name: default
# Reference to upper''s `metadata.namespace`
namespace: default
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
Está bien explicado aquí developer.ibm.com/recipes/tutorials/…
Desde el interior del pod, se puede acceder al servidor de API de Kubernetes directamente en " https: //kubernetes.default ". Por defecto, utiliza la "cuenta de servicio predeterminada" para acceder al servidor api.
Por lo tanto, también necesitamos pasar un "ca cert" y un "token de cuenta de servicio predeterminado" para autenticarnos con el servidor api.
el archivo del certificado se almacena en la siguiente ubicación dentro del pod: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
y el token de cuenta de servicio predeterminado en: /var/run/secrets/kubernetes.io/serviceaccount/token
Puede usar el cliente godaddy de nodejs kubbernetes .
let getRequestInfo = () => {
return {
url: "https://kubernetes.default",
ca: fs.readFileSync(''/var/run/secrets/kubernetes.io/serviceaccount/ca.crt'').toString(),
auth: {
bearer: fs.readFileSync(''/var/run/secrets/kubernetes.io/serviceaccount/token'').toString(),
},
timeout: 1500
};
}
let initK8objs = () =>{
k8obj = getRequestInfo();
k8score = new Api.Core(k8obj),
k8s = new Api.Api(k8obj);
}
En la documentación oficial encontré esto:
https://kubernetes.io/docs/tasks/administer-cluster/access-cluster-api/#accessing-the-api-from-a-pod
Aparentemente me faltaba un token de seguridad que no necesitaba en una versión anterior de Kubernetes. A partir de eso, ideé lo que creo que es una solución más simple que ejecutar un proxy o instalar Golang en mi contenedor. Vea este ejemplo que obtiene la información, desde la API, para el contenedor actual:
KUBE_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
curl -sSk -H "Authorization: Bearer $KUBE_TOKEN" /
https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1/namespaces/default/pods/$HOSTNAME
También utilizo incluir un binario simple, jq ( http://stedolan.github.io/jq/download/ ), para analizar el json para su uso en scripts de bash.
La adición más importante a los detalles ya mencionados anteriormente es que el pod desde el que está intentando acceder al servidor API debe tener las capacidades de RBAC para hacerlo.
Cada entidad en el sistema k8s se identifica mediante una cuenta de servicio (como la cuenta de usuario que se utiliza para los usuarios). Según las capacidades de RBAC, se completa el token de cuenta de servicio (/var/run/secrets/kubernetes.io/serviceaccount/token). Los enlaces kube-api (p. Ej., Pykube) pueden tomar este token como entrada al crear una conexión a los servidores kube-api. Si el pod tiene las capacidades correctas de RBAC, el pod podrá establecer la conexión con el servidor kube-api.
Me encontré con este problema al intentar acceder a la API desde un pod usando Go Code. A continuación se muestra lo que implementé para que funcione, si alguien se encuentra con esta pregunta que quiera usar Go también.
El ejemplo usa un recurso de pod, para el cual debe usar la biblioteca de
client-go
si está trabajando con objetos nativos de kubernetes.
El código es más útil para quienes trabajan con CustomResourceDefintions.
serviceHost := os.GetEnv("KUBERNETES_SERVICE_HOST")
servicePort := os.GetEnv("KUBERNETES_SERVICE_PORT")
apiVersion := "v1" // For example
namespace := default // For example
resource := "pod" // For example
httpMethod := http.MethodGet // For Example
url := fmt.Sprintf("https://%s:%s/apis/%s/namespaces/%s/%s", serviceHost, servicePort, apiVersion, namespace, resource)
u, err := url.Parse(url)
if err != nil {
panic(err)
}
req, err := http.NewRequest(httpMethod, u.String(), bytes.NewBuffer(payload))
if err != nil {
return err
}
caToken, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token")
if err != nil {
panic(err) // cannot find token file
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", string(caToken)))
caCertPool := x509.NewCertPool()
caCert, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt")
if err != nil {
return panic(err) // Can''t find cert file
}
caCertPool.AppendCertsFromPEM(caCert)
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: caCertPool,
},
},
}
resp, err := client.Do(req)
if err != nil {
log.Printf("sending helm deploy payload failed: %s", err.Error())
return err
}
defer resp.Body.Close()
// Check resp.StatusCode
// Check resp.Status
Para quien esté usando Google Container Engine (impulsado por Kubernetes):
Una simple llamada a
https://kubernetes
desde el clúster utilizando
este cliente de kubernetes para Java
funciona.
Tuve un problema de autenticación similar en GKE, donde las secuencias de comandos de Python arrojaron excepciones de repente. La solución que funcionó para mí fue dar permiso a los pods a través del rol
spec:
serviceAccountName: secret-access-sa
containers:
...
para más información ingrese la descripción del enlace aquí
Usando el cliente Python kubernetes ..
from kubernetes import client, config
config.load_incluster_config()
v1_core = client.CoreV1Api()
versión de wget:
KUBE_TOKEN=$(</var/run/secrets/kubernetes.io/serviceaccount/token)
wget -vO- --ca-certificate /var/run/secrets/kubernetes.io/serviceaccount/ca.crt --header "Authorization: Bearer $KUBE_TOKEN" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1/namespaces/default/pods/$HOSTNAME
curl -v -cacert <path to>/ca.crt --cert <path to>/kubernetes-node.crt --key <path to>/kubernetes-node.key https://<ip:port>
Mi versión de k8s es 1.2.0, y en otras versiones se supone que también funciona ^ ^