Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: do not reuse connections per default #105

Merged
merged 5 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci-helm-deploy-nginx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.20'
go-version: '1.21'
- name: GoReleaser
uses: goreleaser/goreleaser-action@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-helm-deploy-traefik.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.20'
go-version: '1.21'
- name: GoReleaser
uses: goreleaser/goreleaser-action@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-kustomize-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.20'
go-version: '1.21'
- name: GoReleaser
uses: goreleaser/goreleaser-action@v4
with:
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ jobs:
lint-go:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v5
with:
go-version: '1.21'
- uses: actions/checkout@v4
- uses: golangci/golangci-lint-action@v3
with:
Expand All @@ -26,7 +29,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.20'
go-version: '1.21'
- name: Run unit tests
run: go test -race -covermode atomic -coverprofile=profile.cov ./...
- name: Send coverage report
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.20'
go-version: '1.21'
- name: Login to DockerHub
uses: docker/login-action@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ linters:
- gochecknoglobals
- gochecknoinits
- gocognit
- goconst
# - goconst
- gocritic
- gocyclo
- gofmt
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ The following command can be used to install kubenurse with Helm: `helm upgrade
| check_me_service | Sets `KUBENURSE_CHECK_ME_SERVICE` environment variable | `true` |
| check_neighbourhood | Sets `KUBENURSE_CHECK_NEIGHBOURHOOD` environment variable | `true` |
| check_interval | Sets `KUBENURSE_CHECK_INTERVAL` environment variable | `5s` |
| reuse_connections | Sets `KUBENURSE_REUSE_CONNECTIONS` environment variable | `false` |
| use_tls | Sets `KUBENURSE_USE_TLS` environment variable | `false` |
| cert_file | Sets `KUBENURSE_CERT_FILE` environment variable | |
| cert_key | Sets `KUBENURSE_CERT_KEY` environment variable | |
Expand Down Expand Up @@ -91,6 +92,7 @@ kubenurse is configured with environment variables:
- `KUBENURSE_CHECK_ME_SERVICE`: If this is `"true"`, kubenurse will perform the check [Me Service](#Me Service). default is "true"
- `KUBENURSE_CHECK_NEIGHBOURHOOD`: If this is `"true"`, kubenurse will perform the check [Neighbourhood](#Neighbourhood). default is "true"
- `KUBENURSE_CHECK_INTERVAL`: the frequency to perform kubenurse checks. the string should be formatted for [time.ParseDuration](https://pkg.go.dev/time#ParseDuration). defaults to `5s`
- `KUBENURSE_REUSE_CONNECTIONS`: whether to reuse connections or not for all checks. default is "false"
- `KUBENURSE_HISTOGRAM_BUCKETS`: optional comma-separated list of float64, used in place of the [default prometheus histogram buckets](https://pkg.go.dev/github.com/prometheus/[email protected]/prometheus#DefBuckets)
- `KUBENURSE_USE_TLS`: If this is `"true"`, enable TLS endpoint on port 8443
- `KUBENURSE_CERT_FILE`: Certificate to use with TLS endpoint
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module github.com/postfinance/kubenurse

go 1.17
go 1.21

toolchain go1.21.5

require (
github.com/prometheus/client_golang v1.18.0
Expand Down
1,702 changes: 0 additions & 1,702 deletions go.sum

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions helm/kubenurse/templates/daemonset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ spec:
value: {{ .Values.check_neighbourhood | quote }}
- name: KUBENURSE_CHECK_INTERVAL
value: {{ .Values.check_interval }}
- name: KUBENURSE_REUSE_CONNECTIONS
value: {{ .Values.reuse_connections | quote }}
- name: KUBENURSE_SHUTDOWN_DURATION
value: {{ .Values.shutdown_duration }}
- name: KUBENURSE_USE_TLS
Expand Down
2 changes: 2 additions & 0 deletions helm/kubenurse/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ check_api_me_service: true
check_neighbourhood: true
# KUBENURSE_CHECK_INTERVAL
check_interval: 5s
# KUBENURSE_REUSE_CONNECTIONS
reuse_connections: false
# KUBENURSE_SHUTDOWN_DURATION
shutdown_duration: 5s
# KUBENURSE_USE_TLS
Expand Down
25 changes: 22 additions & 3 deletions internal/servicecheck/servicecheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package servicecheck

import (
"context"
"crypto/tls"
"fmt"
"log"
"net"
"net/http"
"os"
"time"
Expand Down Expand Up @@ -47,11 +49,28 @@ func New(_ context.Context, discovery *kubediscovery.Client, promRegistry *prome
promRegistry.MustRegister(errorCounter, durationHistogram)

// setup http transport
transport, err := generateRoundTripper(os.Getenv("KUBENURSE_EXTRA_CA"), os.Getenv("KUBENURSE_INSECURE") == "true")
tlsConfig, err := generateTLSConfig(os.Getenv("KUBENURSE_EXTRA_CA"))
if err != nil {
log.Printf("using default transport: %s", err)
log.Printf("cannot generate tlsConfig with KUBENURSE_EXTRA_CA: %s", err)

transport = http.DefaultTransport
tlsConfig = &tls.Config{MinVersion: tls.VersionTLS12}
}

tlsConfig.InsecureSkipVerify = os.Getenv("KUBENURSE_INSECURE") == "true"
dialer := &net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}
transport := &http.Transport{
TLSClientConfig: tlsConfig,
Proxy: http.ProxyFromEnvironment,
DialContext: dialer.DialContext,
ForceAttemptHTTP2: true,
DisableKeepAlives: os.Getenv("KUBENURSE_REUSE_CONNECTIONS") != "true",
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}

httpClient := &http.Client{
Expand Down
24 changes: 11 additions & 13 deletions internal/servicecheck/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ import (

const (
//nolint:gosec // This is the well-known path to Kubernetes serviceaccount tokens.
tokenFile = "/var/run/secrets/kubernetes.io/serviceaccount/token"
caFile = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
K8sTokenFile = "/var/run/secrets/kubernetes.io/serviceaccount/token"
k8sCAFile = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
)

// doRequest does an http request only to get the http status code
func (c *Checker) doRequest(url string) (string, error) {
// Read Bearer Token file from ServiceAccount
token, err := os.ReadFile(tokenFile)
token, err := os.ReadFile(K8sTokenFile)
if err != nil {
return errStr, fmt.Errorf("load kubernetes serviceaccount token from %s: %w", tokenFile, err)
return errStr, fmt.Errorf("load kubernetes serviceaccount token from %s: %w", K8sTokenFile, err)
}

req, _ := http.NewRequest("GET", url, http.NoBody)
Expand All @@ -46,18 +46,18 @@ func (c *Checker) doRequest(url string) (string, error) {
return resp.Status, errors.New(resp.Status)
}

// generateRoundTripper returns a custom http.RoundTripper, including the k8s CA.
func generateRoundTripper(extraCA string, insecure bool) (http.RoundTripper, error) {
// generateTLSConfig returns a TLSConfig including K8s CA and the user-defined extraCA
func generateTLSConfig(extraCA string) (*tls.Config, error) {
// Append default certpool
rootCAs, _ := x509.SystemCertPool()
if rootCAs == nil {
rootCAs = x509.NewCertPool()
}

// Append ServiceAccount cacert
caCert, err := os.ReadFile(caFile)
caCert, err := os.ReadFile(k8sCAFile)
if err != nil {
return nil, fmt.Errorf("could not load certificate %s: %w", caFile, err)
return nil, fmt.Errorf("could not load certificate %s: %w", k8sCAFile, err)
}

if ok := rootCAs.AppendCertsFromPEM(caCert); !ok {
Expand All @@ -78,11 +78,9 @@ func generateRoundTripper(extraCA string, insecure bool) (http.RoundTripper, err

// Configure transport
tlsConfig := &tls.Config{
InsecureSkipVerify: insecure, //nolint:gosec // Can be true if the user requested this.
RootCAs: rootCAs,
RootCAs: rootCAs,
MinVersion: tls.VersionTLS12,
}

transport := &http.Transport{TLSClientConfig: tlsConfig}

return transport, nil
return tlsConfig, nil
}
Loading