Skip to content

Commit

Permalink
Switch to kubernetes cluster dns for incluster url everywhere (#876)
Browse files Browse the repository at this point in the history
* Switch to kubernetes dns for incluster url everywhere

This is the recommended, and only documented method on https://kubernetes.io/docs/tasks/run-application/access-api-from-pod/
The legacy method has issues with ipv6 and it's time to retire it.

We trialled the new method for 6months via #587 without any reports.

Closes #874

Signed-off-by: clux <sszynrae@gmail.com>

* remove code for legacy methods, was never actually made public

Signed-off-by: clux <sszynrae@gmail.com>

* simplify kube_dns fn with less unwraps

Signed-off-by: clux <sszynrae@gmail.com>
  • Loading branch information
clux committed Apr 13, 2022
1 parent 91c054c commit dd0b258
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 92 deletions.
85 changes: 1 addition & 84 deletions kube-client/src/config/incluster_config.rs
@@ -1,12 +1,5 @@
use std::env;

use thiserror::Error;

// Old method to connect to kubernetes
const SERVICE_HOSTENV: &str = "KUBERNETES_SERVICE_HOST";
const SERVICE_PORTENV: &str = "KUBERNETES_SERVICE_PORT";
// New method to connect to kubernetes
const SERVICE_DNS: &str = "kubernetes.default.svc";
// Mounted credential files
const SERVICE_TOKENFILE: &str = "/var/run/secrets/kubernetes.io/serviceaccount/token";
const SERVICE_CERTFILE: &str = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt";
Expand All @@ -15,14 +8,6 @@ const SERVICE_DEFAULT_NS: &str = "/var/run/secrets/kubernetes.io/serviceaccount/
/// Errors from loading in-cluster config
#[derive(Error, Debug)]
pub enum Error {
/// Required envionment variables were not set
#[error(
"missing environment variables {} and/or {}",
SERVICE_HOSTENV,
SERVICE_PORTENV
)]
MissingEnvironmentVariables,

/// Failed to read the default namespace for the service account
#[error("failed to read the default namespace: {0}")]
ReadDefaultNamespace(#[source] std::io::Error),
Expand All @@ -40,40 +25,8 @@ pub enum Error {
ParseCertificates(#[source] pem::PemError),
}

/// Returns Kubernetes address from specified environment variables.
pub fn kube_server() -> Result<http::Uri, Error> {
kube_host_port()
.ok_or(Error::MissingEnvironmentVariables)?
.parse::<http::Uri>()
.map_err(Error::ParseClusterUrl)
}

pub fn kube_dns() -> http::Uri {
http::Uri::builder()
.scheme("https")
.authority(SERVICE_DNS)
.path_and_query("/")
.build()
.unwrap()
}

fn kube_host_port() -> Option<String> {
let host = kube_host()?;
let port = kube_port()?;
if host.contains(":") {
// IPv6 cluster
Some(format!("https://[{}]:{}", host, port))
} else {
Some(format!("https://{}:{}", host, port))
}
}

fn kube_host() -> Option<String> {
env::var(SERVICE_HOSTENV).ok()
}

fn kube_port() -> Option<String> {
env::var(SERVICE_PORTENV).ok()
http::Uri::from_static("https://kubernetes.default.svc/")
}

pub fn token_file() -> String {
Expand All @@ -90,39 +43,3 @@ pub fn load_cert() -> Result<Vec<Vec<u8>>, Error> {
pub fn load_default_ns() -> Result<String, Error> {
std::fs::read_to_string(&SERVICE_DEFAULT_NS).map_err(Error::ReadDefaultNamespace)
}

#[test]
fn test_kube_host() {
let expected = "fake.io";
env::set_var(SERVICE_HOSTENV, expected);
assert_eq!(kube_host().unwrap(), expected);
kube_dns(); // verify kube_dns always unwraps
}

#[test]
fn test_kube_port() {
let expected = "8080";
env::set_var(SERVICE_PORTENV, expected);
assert_eq!(kube_port().unwrap(), expected);
}

#[test]
fn test_kube_server() {
let host = "fake.io";
let port = "8080";
env::set_var(SERVICE_HOSTENV, host);
env::set_var(SERVICE_PORTENV, port);
assert_eq!(kube_server().unwrap(), "https://fake.io:8080");
}

#[test]
fn test_kube_server_ipv6() {
let host = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
let port = "8080";
env::set_var(SERVICE_HOSTENV, host);
env::set_var(SERVICE_PORTENV, port);
assert_eq!(
kube_server().unwrap(),
"https://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080"
);
}
9 changes: 1 addition & 8 deletions kube-client/src/config/mod.rs
Expand Up @@ -192,14 +192,7 @@ impl Config {
/// and relies on you having the service account's token mounted,
/// as well as having given the service account rbac access to do what you need.
pub fn from_cluster_env() -> Result<Self, InClusterError> {
let cluster_url = if cfg!(feature = "rustls-tls") {
// try rolling out new method for rustls which does not support ip based urls anyway
// see https://github.com/kube-rs/kube-rs/issues/587
incluster_config::kube_dns()
} else {
incluster_config::kube_server()?
};

let cluster_url = incluster_config::kube_dns();
let default_namespace = incluster_config::load_default_ns()?;
let root_cert = incluster_config::load_cert()?;

Expand Down

0 comments on commit dd0b258

Please sign in to comment.