Question: How to: [⏫](#contents) Get on/off CPU profiles with [fgprof](https://github.com/felixge/fgprof)

Answer:
This tool can be more illustrative of Go profiles than standard Go profiling. — [@felixge](https://github.com/felixge)

```go
package main

import (
  "log"
  "net/http"
  _ "net/http/pprof"

  "github.com/felixge/fgprof"
)

func main() {
  http.DefaultServeMux.Handle("/debug/fgprof", fgprof.Handler())
  go func() {
    log.Println(http.ListenAndServe(":6060", nil))
  }()

  //
```
}
```
```


Question: How to: [⏫](#contents) Make alternative documentation with [golds](https://github.com/go101/golds)

Answer:
It has additional information like implementations of interface; promoted methods. The tool has nice minimalistic aesthetics. — [Tapir Liu](https://www.tapirgames.com)

```
golds ./...
```
Requirements
```
go install go101.org/golds@latest
```


Question: How to: [⏫](#contents) Read Go binary documentation in `man` format with [goman](https://github.com/appliedgocode/goman)

Answer:
This tool fetches the repo's readme as a man page replacement. — [@christophberger](https://github.com/christophberger)

```
goman
```
Requirements
```
go install github.com/appliedgocode/goman@latest
```


Question: How to: [⏫](#contents) Generate badge with [gobadge](https://github.com/AlexBeauchemin/gobadge)

Answer:
This tool will generate instructions for [shields.io](https://shields.io) to generate badge. It can read `coverprofile`. There is also GitHub Action that utilizes it and stores badge in the same repo, [coverage-badge-go](https://github.com/tj-actions/coverage-badge-go). — [@AlexBeauchemin](https://github.com/AlexBeauchemin)

```
gobadge -filename=coverage.out
gobadge -label="Go Coverage" -value=55.6% -color=blue -target=OTHER_README.md
gobadge -yellow=60 -green=80
gobadge -color=ff69b4
gobadge -link=https://github.com/project/repo/actions/workflows/test.yml
```
Requirements
```
go install github.com/AlexBeauchemin/gobadge@latest
```


Question: How to: [⏫](#contents) Generate README.md based on GoDoc comments with [goreadme](https://github.com/posener/goreadme)

Answer:
It can be used as a command line tool, as Github action, or as a pre-commit hook. — [@posener](https://github.com/posener)

```
goreadme
goreadme -variables -functions -methods -badge-godoc
goreadme -badge-godoc -constants -functions -methods -recursive -types -variables > README.md
```

Requirements
```
go install github.com/posener/goreadme/cmd/goreadme@latest
```


Question: How to: [⏫](#contents) :gift: display contents of a module with [go-mod-viewer](https://go-mod-viewer.appspot.com/https://go-mod-viewer.appspot.com/)

Answer:
Go mod viewer displays text files from Go modules stored in the Go module proxy. The URL schema is https://go-mod-viewer.appspot.com/
@
/
. — [@rsc](https://github.com/rsc)

```
https://go-mod-viewer/rsc.io/quote@v1.5.2/README.md#L1
```


Question: How to: [⏫](#contents) Run Turtle Graphics online with [goplay.space](https://goplay.space/#wT_eZWJT69)

Answer:
This absolutely adorable visualization is an excellent online resource to learn programming. — [@iafan](https://github.com/iafan)

```go
package main

import (
  "fmt"
)

func main() {
  fmt.Println(`
    draw mode

    say Let's start...
    right 18
    color red

    forward 7
    say One...
    right 144

    forward 7
    say Two...
    right 144

    forward 7
    say Three...
    right 144

    forward 7
    say Four...
    right 144

    forward 7
    say We've got a star!
    right 144
  `)
}
```


Question: How to: Style Guide

Answer:
- [Google](https://google.github.io/styleguide/go)

- [Uber](https://github.com/uber-go/guide)

- [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments)


Question: How to: [⏫](#contents) Run official vulnerability check with [govulncheck](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck)

Answer:
It uses static analysis of source code or a binary's symbol table to narrow down reports to only those that could affect the application. By default, govulncheck makes requests to the Go vulnerability database at https://vuln.go.dev. Requests to the vulnerability database contain only module paths, not code or other properties of your program. See https://vuln.go.dev/privacy.html for more. — Go Core team

```
govulncheck ./...
```

Example
```
vulnerability data from https://vuln.go.dev (last modified 2023-06-01 21:27:40 +0000 UTC).

Scanning your code and 1952 packages across 202 dependent modules for known vulnerabilities...
Your code is affected by 2 vulnerabilities from 1 module.

Vulnerability #1: GO-2023-1571
  A maliciously crafted HTTP/2 stream could cause excessive CPU
  consumption in the HPACK decoder, sufficient to cause a denial
  of service from a small number of small requests.

  More info: https://pkg.go.dev/vuln/GO-2023-1571

  Module: golang.org/x/net
    Found in: golang.org/x/net@v0.1.1-0.20221027164007-c63010009c80
    Fixed in: golang.org/x/net@v0.7.0

    Call stacks in your code:
      cmd/kube-controller-manager/app/controllermanager.go:216:40: k8s.io/kubernetes/cmd/kube-controller-manager/app.Run calls k8s.io/apiserver/pkg/server.SecureServingInfo.Serve, which eventually calls golang.org/x/net/http2.ConfigureServer
        requirements:
          - go install golang.org/x/vuln/cmd/govulncheck@latest
```


Question: How to: [⏫](#contents) Detect escalated privileges in dependencies with [capslock](https://github.com/google/capslock)

Answer:
Capslock is a capability analysis CLI for Go packages that informs users of which privileged operations a given package can access. This works by classifying the capabilities of Go packages by following transitive calls to privileged standard library operations. The recent increase in supply chain attacks targeting open source software has highlighted that third party dependencies should not be inherently trusted. Capabilities indicate what permissions a package has access to, and can be used in conjunction with other security signals to indicate which code requires additional scrutiny before it can be considered trusted. — Google

```
capslock -packages=./...
```

Example
```
...
CAPABILITY_ARBITRARY_EXECUTION: 317 references
CAPABILITY_EXEC: 317 references
CAPABILITY_FILES: 318 references
CAPABILITY_MODIFY_SYSTEM_STATE: 20 references
CAPABILITY_NETWORK: 317 references
CAPABILITY_OPERATING_SYSTEM: 124 references
CAPABILITY_READ_SYSTEM_STATE: 317 references
CAPABILITY_REFLECT: 348 references
CAPABILITY_RUNTIME: 317 references
CAPABILITY_SYSTEM_CALLS: 12 references
CAPABILITY_UNANALYZED: 332 references
CAPABILITY_UNSAFE_POINTER: 335 references
```

Requirements
```
go install github.com/google/capslock/cmd/capslock@latest
```


Question: How to: [⏫](#contents) Run static analysis with [gosec](https://github.com/securego/gosec)

Answer:
This tool inspects source code for security problems by scanning the Go AST and SSA code representation. There are numerous rules it checks. — [@ccojocar](https://github.com/ccojocar)

```
gosec ./...
```

Requirements
```
go install github.com/securego/gosec/v2/cmd/gosec@latest
```


Question: How to: [⏫](#contents) Perform Taint Analysis with [taint](https://github.com/picatz/taint)

Answer:
Taint analysis is a technique for identifying the flow of sensitive data through a program. It can be used to identify potential security vulnerabilities, such as SQL injection or cross-site scripting (XSS) attacks, by understanding how this data is used and transformed as it flows through the code. This package provides tools to performs such analysis. Included tool is performing SQL injection taint analysis. — [@picatz](https://github.com/picatz)

```
sqli main.go
```

```go
package main

import (
        "database/sql"
        "net/http"
)

func business(db *sql.DB, q string) {
        db.Query(q) // potential sql injection
}

func run() {
        db, _ := sql.Open("sqlite3", ":memory:")

        mux := http.NewServeMux()

        mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
                business(db, r.URL.Query().Get("sql-query"))
        })

        http.ListenAndServe(":8080", mux)
}

func main() {
        run()
}
```

Example
```
./sql/injection/testdata/src/example/main.go:9:10: potential sql injection
```

Requirements
```
go install github.com/picatz/taint/cmd/sqli@latest
```


Question: How to: [⏫](#contents) Use Microsoft Go compiler with [microsoft/go](https://github.com/microsoft/go)

Answer: This is modified version of Go that can be used to build FIPS 140-2 compliant applications. — [@microsoft](https://github.com/microsoft)


Question: How to: [⏫](#contents) Run default static analysis with `go vet`

Answer:
Official tool for static analysis of Go programs, with 27+ static analyzers. — official Go team

```
go vet ./...
```


Question: How to: [⏫](#contents) Run custom static analysis tool with `go vet`

Answer:
Standard `go vet` can be used to run custom analyzers binaries. Third party analyzers are supported. Lots of official analyzers not included by default into `go vet`. Analyzer has to satisfy interface and command described here https://pkg.go.dev/golang.org/x/tools/go/analysis. Refer for https://pkg.go.dev/golang.org/x/tools/go/analysis/passes for full list of official Go analyzers. — official Go team

```
go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
go vet -vettool=$(which shadow)
```


Question: How to: [⏫](#contents) Detect most common issues with [staticcheck](https://github.com/dominikh/go-tools)

Answer:
Start custom linters with this well-known linter. It contains 150+ high quality low false positive rate linters. It is widely adopted by Open Source and tech companies. [staticcheck.io](https://staticcheck.io/). — [@dominikh](https://github.com/dominikh)

```
staticcheck ./...
```

Requirements
```
go install honnef.co/go/tools/cmd/staticcheck@latest
```


Question: How to: [⏫](#contents) Detect potential Nil panics with [nilaway](https://github.com/uber-go/nilaway)

Answer:
This tool employs sophisticated static analysis techniques to catch Nil dereferences. More details in [blog](https://www.uber.com/en-IN/blog/nilaway-practical-nil-panic-detection-for-go/). — Uber

```
nilaway ./...
```
Requirements
```
go install go.uber.org/nilaway/cmd/nilaway@latest
```


Question: How to: [⏫](#contents) Detect most common issues with [go-critic](https://github.com/go-critic/go-critic)

Answer:
This linting aggregator and runner is similar to staticcheck. It has 100+ linting rules. It is based on Go [Code Review Comments](https://go.dev/wiki/CodeReviewComments) style guide that is used in core Go project itself. It has styling, security, performance rules. It has minimal dependencies and implements rules itself. It exports all analysers into `golang.org/x/tools/go/analysis` toolchain. — [@quasilyte](https://github.com/quasilyte)

```
gocritic check ./...
```

Requirements
```
go install -v github.com/go-critic/go-critic/cmd/gocritic@latest
```


Question: How to: [⏫](#contents) Reference and run common linters with [golangci-lint](https://golangci-lint.run)

Answer:
This tool has comprehensive list of linters. Owners of this aggregator keep track of active linters, their versions, and optimal configs. It contains many optimizations to make linters run fast by parallelism, distributing binaries and Docker images, utilising `golang.org/x/tools/go/analysis` toolchain.

```
golangci-lint run
```

Example
```
server/web/filter/opentracing/filter.go:21:2: import-alias-naming: import name (logKit) must match the regular expression: ^[a-z][a-z0-9]{0,}$ (revive)
core/utils/pagination/paginator.go:65:3: G104: Errors unhandled. (gosec)
core/utils/pagination/utils.go:33:2: bare-return: avoid using bare returns, please add return expressions (revive)
server/web/grace/server.go:358:3: exitAfterDefer: log.Fatalf will exit, and `defer regLock.Unlock()` will not run (gocritic)
server/web/filter/prometheus/filter.go:90:40: "2006-01-02 15:04:05" can be replaced by time.DateTime (usestdlibvars)
core/utils/slice.go:47:20: builtinShadow: shadowing of predeclared identifier: min (gocritic)
core/utils/utils.go:54:3: ifElseChain: rewrite if-else to switch statement (gocritic)
client/orm/hints/db_hints_test.go:95:2: expected-actual: need to reverse actual and expected values (testifylint)
core/config/env/env.go:95:15: fmt.Errorf can be replaced with errors.New (perfsprint)
```

Requirements
```
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin latest
```


Question: How to: [⏫](#contents) Detect non-exhaustive switch and map with [exhaustive](https://github.com/nishanths/exhaustive)

Answer:
This `go vet` compatible analyzer checks for exhaustive switch statements and map literals. It works for enums with underlying integer, float, or string types (struct based enums are not supported). — [@nishanths](https://github.com/nishanths)

```
exhaustive ./...
```

```go
package token

type Token int

const (
  Add Token = iota
  Subtract
  Multiply
  Quotient
  Remainder
)

package calc

import "token"

func f(t token.Token) {
  switch t {
  case token.Add:
  case token.Subtract:
  case token.Multiply:
  default:
  }
}

func g(t token.Token) string {
  return map[token.Token]string{
    token.Add:      "add",
    token.Subtract: "subtract",
    token.Multiply: "multiply",
  }[t]
}
```

Example
```
calc.go:6:2: missing cases in switch of type token.Token: Quotient, Remainder
calc.go:15:9: missing map keys of type token.Token: Quotient, Remainder
```

Requirements
```
go install github.com/nishanths/exhaustive/cmd/exhaustive@latest
```


Question: How to: [⏫](#contents) Detect structs with uninitialized fields with [go-exhaustruct](https://github.com/GaijinEntertainment/go-exhaustruct)

Answer:
This tool finds instantiations of structs with zero values. It supports struct tags to mark fields as optional. This may help to prevent unexpected zero values. — [@xobotyi](https://github.com/xobotyi)

```
exhaustruct ./...
```

```go
type Shape struct {
  Length int
  Width  int
  volume    int
  Perimeter int `exhaustruct:"optional"`
}

// valid
var a Shape = Shape{
  Length: 5,
  Width:  3,
  volume: 5,
}

// invalid, `volume` is missing
var b Shape = Shape{
  Length: 5,
  Width:  3,
}
```

Requirements
```
go get -u github.com/GaijinEntertainment/go-exhaustruct/v3/cmd/exhaustruct
```


Question: How to: [⏫](#contents) :gift: Detect missing cascade calls with [go-lint-cascade](https://github.com/nikolaydubina/go-lint-cascade)

Answer:
For example, if you have cascade calls for WithDefaults() in nested config structs, this linter will detect if you missed any WithDefaults() calls. — [@nikolaydubina](https://github.com/nikolaydubina)

```
go-lint-cascade ./...
```

```go
type Config struct {
    DB DBConfig
}

func (s Config) WithDefaults() Config {
    // ERROR: Missing s.DB = s.DB.WithDefaults()
    return s
}

type DBConfig struct {
    Port int
}

func (s DBConfig) WithDefaults() DBConfig {
    if s.Port == 0 {
        s.Port = 42
    }
    return s
}
```

Requirements
```
go install github.com/nikolaydubina/go-lint-cascade@latest
```


Question: How to: [⏫](#contents) Detect unreachable functions with [deadcode](https://pkg.go.dev/golang.org/x/tools/cmd/deadcode)

Answer:
This static analysis tool detects when functions can not be reached in any execution. There is also `-test` mode that shows if function is reachable by any of tests. — [Alan Donovan](https://github.com/adonovan), official Go team

```
deadcode .
```

Example
```
greet.go:23: unreachable func: goodbye
greet.go:20: unreachable func: Goodbyer.Greet
```

Requirements
```
go install golang.org/x/tools/cmd/deadcode@latest
```


Question: How to: [⏫](#contents) Detect unsafe code with [go-safer](https://github.com/jlauinger/go-safer)

Answer:
Find incorrect uses of `reflect.SliceHeader`, `reflect.StringHeader`, and unsafe casts between structs with architecture-sized fields. Research paper ["Uncovering the Hidden Dangers Finding Unsafe Go Code in the Wild"](https://arxiv.org/abs/2010.11242) presented at 19th IEEE International Conference on Trust, Security and Privacy in Computing and Communications (TrustCom 2020). — [@jlauinger](https://github.com/jlauinger)

```
go-safer ./...
```

Example
```


Question: How to: github.com/jlauinger/go-safer/passes/sliceheader/testdata/src/bad/composite_literal

Answer:
composite_literal/composite_literal.go:10:9: reflect header composite literal found
composite_literal/composite_literal.go:10:9: reflect header composite literal found


Question: How to: github.com/jlauinger/go-safer/passes/sliceheader/testdata/src/bad/header_in_struct

Answer:
header_in_struct/header_in_struct.go:16:2: assigning to reflect header object
```

Requirements
```
go install github.com/jlauinger/go-safer@latest
```


Question: How to: [⏫](#contents) Detect `panic` without explaining comment with [panic-linter](https://github.com/ldemailly/panic-linter)

Answer:
Panic should only be used very sparingly, for catching bugs basically, and thus deserve a comment to confirm that that's indeed the case. — [@ldemailly](https://github.com/ldemailly)

```go


Question: How to: [⏫](#contents) Detect unnecessary type conversions with [unconvert](https://github.com/mdempsky/unconvert)

Answer:
Identify expressions like `T(x)` where `x` is already has type `T`. This tool can identify conversions that force intermediate rounding. It also can overwrite files with fix. This tool is not using `golang.org/x/tools/go/analysis` toolchain. — [@mdempsky](https://github.com/mdempsky)

```
unconvert ./...
```

```
$ unconvert -v bytes fmt
GOROOT/src/bytes/reader.go:117:14: unnecessary conversion
                abs = int64(r.i) + offset
                          ^
GOROOT/src/fmt/print.go:411:21: unnecessary conversion
        p.fmt.integer(int64(v), 16, unsigned, udigits)
                          ^
```

Requirements
```
go install github.com/mdempsky/unconvert@latest
```


Question: How to: [⏫](#contents) Detect global variables with [gochecknoglobals](https://github.com/leighmcculloch/gochecknoglobals)

Answer:
Global variables are an input to functions that is not visible in the functions signature, complicate testing, reduces readability and increase the complexity of code. However, sometimes global variables make sense. This tool skips such common scenarios. This tool can be used in CI, albeit it is very strict. This tool is useful for investigations. — [@leighmcculloch](https://github.com/leighmcculloch)

```
gochecknoglobals ./...
```

Example
```
/Users/nikolaydubina/Workspace/hugo/common/paths/path.go:64:5: fpb is a global variable
/Users/nikolaydubina/Workspace/hugo/common/paths/url.go:50:5: pb is a global variable
/Users/nikolaydubina/Workspace/hugo/common/text/position.go:52:5: positionStringFormatfunc is a global variable
/Users/nikolaydubina/Workspace/hugo/common/text/transform.go:26:5: accentTransformerPool is a global variable
/Users/nikolaydubina/Workspace/hugo/common/herrors/error_locator.go:40:5: SimpleLineMatcher is a global variable
```

Requirements
```
go install 4d63.com/gochecknoglobals@latest
```


Question: How to: [⏫](#contents) Detect slices that could be preallocated with [prealloc](https://github.com/alexkohler/prealloc)

Answer:
Preallocating slices can sometimes significantly improve performance. This tool detects common scenarios where preallocating can be beneficial. This tool is not using `golang.org/x/tools/go/analysis` toolchain. — [@alexkohler](https://github.com/alexkohler)

```
prealloc ./...
```

Example
```
tools/gopls/internal/lsp/source/completion/completion.go:1484 Consider preallocating paths
tools/gopls/internal/lsp/source/completion/package.go:54 Consider preallocating items
tools/gopls/internal/lsp/template/symbols.go:205 Consider preallocating ans
tools/gopls/internal/lsp/template/completion.go:199 Consider preallocating working
tools/gopls/internal/lsp/tests/util.go:32 Consider preallocating notePositions
tools/gopls/internal/lsp/tests/util.go:240 Consider preallocating paramParts
tools/gopls/internal/lsp/tests/util.go:282 Consider preallocating result
tools/gopls/internal/lsp/tests/util.go:309 Consider preallocating got
```

Requirements
```
go install github.com/alexkohler/prealloc@latest
```


Question: How to: [⏫](#contents) Detect unnecessary import aliases with [unimport](https://github.com/alexkohler/unimport)

Answer:
It is common guideline to avoid renaming imports unless there are collisions. This tool detects where original package name would not collide. This tool is useful for investigations. This tool is not using `golang.org/x/tools/go/analysis` toolchain. — [@alexkohler](https://github.com/alexkohler)

```
unimport ./...
```

Example
```
pkg/apis/apiserverinternal/v1alpha1/zz_generated.conversion.go:29 unnecessary import alias runtime
pkg/apis/apiserverinternal/v1alpha1/zz_generated.conversion.go:30 unnecessary import alias apiserverinternal
pkg/apis/apps/v1/zz_generated.conversion.go:25 unnecessary import alias unsafe
pkg/apis/apps/v1/zz_generated.conversion.go:30 unnecessary import alias conversion
pkg/apis/apps/v1/zz_generated.conversion.go:31 unnecessary import alias runtime
pkg/apis/apps/v1/zz_generated.conversion.go:32 unnecessary import alias intstr
pkg/apis/apps/v1/zz_generated.conversion.go:33 unnecessary import alias apps
pkg/apis/apps/v1/zz_generated.conversion.go:34 unnecessary import alias core
pkg/apis/apps/v1beta1/zz_generated.conversion.go:25 unnecessary import alias unsafe
pkg/apis/apps/v1beta1/zz_generated.conversion.go:27 unnecessary import alias v1beta1
pkg/apis/apps/v1beta1/zz_generated.conversion.go:30 unnecessary import alias conversion
pkg/apis/apps/v1beta1/zz_generated.conversion.go:31 unnecessary import alias runtime
```

Requirements
```
go install github.com/alexkohler/unimport@latest
```


Question: How to: [⏫](#contents) Detect unexpected import aliases with [importas](https://github.com/julz/importas)

Answer:
Ensure that import aliases take one of the allowed values. — [@julz](https://github.com/julz)

```
importas -alias knative.dev/serving/pkg/apis/autoscaling/v1alpha1:autoscalingv1alpha1 -alias knative.dev/serving/pkg/apis/serving/v1:servingv1 ./...
```

```go
package main

import (
  v1alpha1 "knative.dev/serving/pkg/apis/autoscaling/v1alpha1" // want `import "knative.dev/serving/pkg/apis/autoscaling/v1alpha1" imported as "v1alpha1" but must be "autoscalingv1alpha1" according to config`
  v1 "knative.dev/serving/pkg/apis/serving/v1"                 // want `import "knative.dev/serving/pkg/apis/serving/v1" imported as "v1" but must be "servingv1" according to config`
)

func main() {
...
```

Requirements
```
go install github.com/julz/importas/cmd/importas@latest
```


Question: How to: [⏫](#contents) Detect inconsistent import aliases with [consistentimports](https://github.com/nikolaydubina/consistentimports)

Answer:
It greatly helps to navigate large codebases when imports have the same aliases. — [@nikolaydubina](https://github.com/nikolaydubina)

```
consistentimports ./...
```

Example
```
-: "k8s.io/utils/net" netutils:4 netutil:1
-: "k8s.io/client-go/listers/core/v1" corelisters:1 listersv1:1 v1listers:1
-: "k8s.io/client-go/informers/core/v1" coreinformers:1 informers:1
-: "k8s.io/api/rbac/v1" rbacv1:4 v1:2
-: "k8s.io/apimachinery/pkg/runtime" runtime:3 kruntime:1
-: "k8s.io/api/imagepolicy/v1alpha1" imagepolicyv1alpha1:1 v1alpha1:1
-: "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis
```

Requirements
```
go install github.com/nikolaydubina/consistentimports@latest
```


Question: How to: [⏫](#contents) Detect naked returns with [nakedret](https://github.com/alexkohler/nakedret)

Answer:
It is common guideline to avoid [naked returns](https://go.dev/wiki/CodeReviewComments#named-result-parameters). Naked return is when function has named return, and return statement does not specify value. This tool is useful for investigations. — [@alexkohler](https://github.com/alexkohler)

```
nakedret ./...
```

Example
```
/kubernetes/pkg/controller/podautoscaler/replica_calculator.go:421:2: naked return in func `groupPods` with 44 lines of code
/kubernetes/pkg/kubelet/container/helpers.go:374:2: naked return in func `MakePortMappings` with 36 lines of code
/kubernetes/pkg/kubelet/config/config.go:350:2: naked return in func `filterInvalidPods` with 17 lines of code
/kubernetes/pkg/kubelet/config/config.go:449:3: naked return in func `checkAndUpdatePod` with 38 lines of code
/kubernetes/pkg/kubelet/config/config.go:471:2: naked return in func `checkAndUpdatePod` with 38 lines of code
/kubernetes/cmd/kube-controller-manager/app/controllermanager.go:717:2: naked return in func `createClientBuilders` with 19 lines of code
/kubernetes/pkg/proxy/topology.go:77:3: naked return in func `CategorizeEndpoints` with 98 lines of code
/kubernetes/pkg/proxy/topology.go:111:3: naked return in func `CategorizeEndpoints` with 98 lines of code
/kubernetes/pkg/proxy/topology.go:119:3: naked return in func `CategorizeEndpoints` with 98 lines of code
/kubernetes/pkg/proxy/topology.go:137:2: naked return in func `CategorizeEndpoints` with 98 lines of code
```

Requirements
```
go install github.com/alexkohler/nakedret/cmd/nakedret@latest
```


Question: How to: [⏫](#contents) Detect mixing pointer and value method receivers with [smrcptr](https://github.com/nikolaydubina/smrcptr)

Answer:
Mixing pointer and value method receivers for the same type is discouraged, as per commong guideline [Go wiki](https://go.dev/wiki/CodeReviewComments#receiver-type) and [Google Go style guide](https://google.github.io/styleguide/go/decisions#receiver-type). — [@nikolaydubina](https://github.com/nikolaydubina)

```
smrcptr ./...
```

```go
type Pancake struct{}

func NewPancake() Pancake { return Pancake{} }

func (s *Pancake) Fry() {}

func (s Pancake) Bake() {}
```

Example
```
smrcptr/internal/bakery/pancake.go:7:1: Pancake.Fry uses pointer
smrcptr/internal/bakery/pancake.go:9:1: Pancake.Bake uses value
```

Requirements
```
go install github.com/nikolaydubina/smrcptr@latest
```


Question: How to: [⏫](#contents) Detect vertical function ordering with [vertfn](https://github.com/nikolaydubina/vertfn)

Answer:
Vertical function ordering is declaring functions before they are used. Based on 'Clean Code' by Robert.C.Martin. — [@nikolaydubina](https://github.com/nikolaydubina)

```
vertfn --verbose ./...
```
Requirements
```
go install github.com/nikolaydubina/vertfn@latest
```


Question: How to: [⏫](#contents) Detect vertical symbol ordering with [refdir](https://github.com/devnev/refdir)

Answer:
This tool goes beyond just vertical ordering of function declarations, it also tracks many other types of symbols. — [@devnev](https://github.com/devnev)

```
refdir --verbose ./...
```
Requirements
```
go install github.com/devnev/refdir@latest
```


Question: How to: [⏫](#contents) Detect tests with wrong `t.Parallel()` usage with [paralleltest](https://github.com/kunwardeep/paralleltest)

Answer:
This linter checks for incorrect usage of `t.Parallel()` calls. It will detect if `t.Parallel()` is missing. — [@kunwardeep](https://github.com/kunwardeep)

```
paralleltest ./...
```

Example
```
/kubernetes/pkg/scheduler/framework/plugins/nodeunschedulable/node_unschedulable_test.go:28:1: Function TestNodeUnschedulable missing the call to method parallel
/kubernetes/pkg/scheduler/framework/plugins/nodevolumelimits/csi_test.go:68:1: Function TestCSILimits missing the call to method parallel
/kubernetes/pkg/scheduler/framework/plugins/nodevolumelimits/csi_test.go:480:2: Range statement for test TestCSILimits missing the call to method parallel in test Run
/kubernetes/pkg/scheduler/framework/plugins/nodevolumelimits/non_csi_test.go:81:1: Function TestEphemeralLimits missing the call to method parallel
```

Requirements
```
go install github.com/kunwardeep/paralleltest@latest
```


Question: How to: [⏫](#contents) Detect tests with wrong `t.Parallel()` usage with [tparallel](https://github.com/moricho/tparallel)

Answer:
This linter checks for incorrect usage of `t.Parallel()` calls. — [@moricho](https://github.com/moricho)

```
go vet -vettool=`which tparallel` ./...
```

Example
```
testdata/src/sample/table_test.go:7:6: Test_Table1 should use t.Cleanup
testdata/src/sample/table_test.go:7:6: Test_Table1 should call t.Parallel on the top level as well as its subtests
testdata/src/sample/table_test.go:30:6: Test_Table2's subtests should call t.Parallel
```

Requirements
```
go install github.com/moricho/tparallel/cmd/tparallel@latest
```


Question: How to: [⏫](#contents) Detect magic numbers with [mnd](https://github.com/tommy-muehle/go-mnd)

Answer:
This tool has heuristics to detect magic numbers. — [@tommy-muehle](https://github.com/tommy-muehle)

```
mnd ./...
```

Example
```
/go-mnd/examples/bad/main.go:18:23: Magic number: 200, in
detected
/go-mnd/examples/bad/main.go:11:12: Magic number: 2, in
detected
```

Requirements
```
go install github.com/tommy-muehle/go-mnd/v2/cmd/mnd@latest
```


Question: How to: [⏫](#contents) Detect magic strings with [goconst](https://github.com/jgautheron/goconst)

Answer:
This tool detects repeated strings. — [@jgautheron](https://github.com/jgautheron)

```
goconst -min-occurrences 5 -output json ./... | jq
```

Example
```
"not reached": [
  {
    "Filename": "tpl/internal/go_templates/texttemplate/hugo_template.go",
    "Offset": 7916,
    "Line": 267,
    "Column": 8
  },
  {
    "Filename": "tpl/internal/go_templates/texttemplate/exec.go",
    "Offset": 15056,
    "Line": 525,
    "Column": 8
  },
  {
    "Filename": "tpl/internal/go_templates/texttemplate/exec.go",
    "Offset": 21354,
    "Line": 699,
    "Column": 8
  },
  {
    "Filename": "tpl/internal/go_templates/texttemplate/exec.go",
    "Offset": 28145,
    "Line": 903,
    "Column": 8
  },
  ...
```

Requirements
```
go install github.com/jgautheron/goconst/cmd/goconst@latest
```


Question: How to: [⏫](#contents) Detect bound checks with [pat/boundcheck](https://github.com/maruel/pat)

Answer:
This tool detects bound checks in source code by analysing compiled code. This is useful for audit. — [@maruel](https://github.com/maruel)

```
boundcheck -pkg ./cmd/nin | less -R
```
Requirements
```
go install github.com/maruel/pat/cmd/...@latest
```


Question: How to: [⏫](#contents) :gift: Detect performance optimizations with [perfsprint](https://github.com/catenacyber/perfsprint)

Answer:
This tool detects possible performance optimizations in source code. It suggests replacing usages of `fmt.Sprintf` and `fmt.Errorf` with more efficient alternatives. — [@catenacyber](https://github.com/catenacyber)

```
perfsprint .
```

```go
package main

import (
  "fmt"
)

var _ = fmt.Errorf("some error")

func Sprintf() {
  _ = fmt.Sprintf("Hello, World!")
  world := "World"
  _ = fmt.Sprintf("Hello %s", world)
  _ = fmt.Sprintf("%d", 42)
  _ = fmt.Sprintf("%d", int64(42))
}
```

Example
```
/testdata/perfsprint.go:7:9: error-format: fmt.Errorf can be replaced with errors.New
/testdata/perfsprint.go:10:6: string-format: fmt.Sprintf can be replaced with just using the string
/testdata/perfsprint.go:12:6: string-format: fmt.Sprintf can be replaced with string concatenation
/testdata/perfsprint.go:13:6: integer-format: fmt.Sprintf can be replaced with faster strconv.Itoa
/testdata/perfsprint.go:14:6: integer-format: fmt.Sprintf can be replaced with faster strconv.FormatInt
/testdata/perfsprint.go:4:2: fiximports: Fix imports
```

Requirements
```
go install github.com/catenacyber/perfsprint@latest
```


Question: How to: [⏫](#contents) Calculate Cognitive Complexity with [gocognit](https://github.com/uudashr/gocognit)

Answer:
Cognitive Complexity as defined in this tool can be more illustrative than Cyclometric Complexity. Research paper ["Cognitive Complexity - a new way of measuring understandability"](https://www.sonarsource.com/docs/CognitiveComplexity.pdf), 2021. — [@uudashr](https://github.com/uudashr)

```
gocognit .
```

```go
// Complexity Cyclomatic=4 Cognitive=7
// Cognitive complexity give higher score compare to cyclomatic complexity.
func SumOfPrimes(max int) int {         // +1
    var total int
    for i := 1; i < max; i++ {          // +1 (cognitive +1, nesting)
        for j := 2; j < i; j++ {        // +1 (cognitive +2, nesting)
            if i%j == 0 {               // +1
                continue OUT
            }
        }
        total += i
    }
    return total
}

// Complexity Cyclomatic=4 Cognitive=1
// Cognitive complexity give lower score compare to cyclomatic complexity.
func GetWords(number int) string {      // +1
    switch number {
        case 1:                         // +1 (cognitive 0)
            return "one"
        case 2:                         // +1 (cognitive 0)
            return "a couple"
        case 3:                         // +1 (cognitive 0)
            return "a few"
        default:
            return "lots"
    }
}
```

Example
```
21 main (BasicSymtabConverter).SymtabFileToTreemap basic_converter.go:23:1
12 symtab parseGoSymtabLine symtab/go_symtab_parser.go:37:1
11 main main main.go:30:1
8 symtab EqSymbolName symtab/symbol_name_parser.go:12:1
7 symtab ParseSymbolName symtab/symbol_name_parser.go:32:1
7 symtab Test_parseGoSymtabLine symtab/go_symtab_parser_private_test.go:5:1
4 symtab Test_ParseSymbolName symtab/symbol_name_parser_private_test.go:5:1
3 main updateNodeNamesWithByteSize main.go:99:1
3 main unique basic_converter.go:119:1
3 symtab (GoSymtabParser).ParseSymtab symtab/go_symtab_parser.go:14:1
2 fmtbytecount ByteCountIEC fmtbytecount/format_bytecount.go:3:1
```

Requirements
```
go install github.com/uudashr/gocognit/cmd/gocognit@latest
```


Question: How to: [⏫](#contents) Calculate Cyclomatic Complexity with [gocyclo](https://github.com/fzipp/gocyclo)

Answer:
Cyclomatic complexity is a code quality metric which can be used to identify code that needs refactoring. It measures the number of linearly independent paths through a function's source code. For example, excessive usage of nested `if` and `for` leads to increased cyclomatic complexity. This tool can report `top-N` and `over`, which makes it suitable for CI as a linter and manual investigation. — [@fzipp](https://github.com/fzipp)

```
gocyclo .
```

Example
```
$ gocyclo -over=5 .
34 examplemodule (*With32FieldsFeatureTransformer).Fit cmd/generate/tests/with32fieldsfp.go:48:1
24 main parseCode cmd/generate/parser.go:83:1
13 examplemodule (*AllTransformersFeatureTransformer).Fit cmd/generate/tests/alltransformersfp.go:27:1
12 examplemodule (*EmployeeFeatureTransformer).Fit cmd/generate/tests/employeefp.go:26:1
11 transformers (*CountVectorizer).TransformInplace transformers/textprocesors.go:84:1
11 structtransformer (*StructTransformer).Transform structtransformer/structtransformer.go:38:1
11 examplemodule (*LargeMemoryTransformerFeatureTransformer).Fit cmd/generate/tests/largememorytransformerfp.go:25:1
10 examplemodule (*WeirdTagsFeatureTransformer).Fit cmd/generate/tests/weirdtagsfp.go:24:1
8 transformers (*SampleNormalizerL2).TransformInplace transformers/samplenormalizers.go:58:1
```

Requirements
```
go install github.com/fzipp/gocyclo/cmd/gocyclo@latest
```


Question: How to: [⏫](#contents) Calculate Cyclomatic Complexity with [cyclop](https://github.com/bkielbasa/cyclop)

Answer:
This linter calculates cyclomatic complexity of functions or packages. It can select minimum complexity and act as blocking linter in CI pipelines. The key offering from this linter is that it can calculate avg cyclomatic complexity on package. — [@bkielbasa](https://github.com/bkielbasa)

```
cyclop ./...


Question: How to: to find packages with avg cyclomatic complexity above maximum

Answer:
cyclop -packageAverage 5 -maxComplexity 10000 ./...
```

Example
```
/kubernetes/test/integration/scheduler/scoring/priorities_test.go:17:1: the average complexity for the package scoring is 6.100000, max is 5.000000
/kubernetes/test/integration/serviceaccount/service_account_test.go:17:1: the average complexity for the package serviceaccount is 10.666667, max is 5.000000
/kubernetes/test/integration/volume/persistent_volumes_test.go:17:1: the average complexity for the package volume is 6.157895, max is 5.000000
/kubernetes/test/list/main_test.go:17:1: the average complexity for the package main is 5.461538, max is 5.000000
/kubernetes/test/typecheck/main_test.go:17:1: the average complexity for the package main is 5.916667, max is 5.000000
/kubernetes/third_party/forked/golang/net/dnsclient_test.go:10:1: the average complexity for the package net is 5.333333, max is 5.000000
```

Requirements
```
go install github.com/bkielbasa/cyclop@latest
```


Question: How to: [⏫](#contents) Calculate age of comments with [go-commentage](https://github.com/nikolaydubina/go-commentage)

Answer:
This go vet compatible tool analyses AST and git and collects details on how far comments drift from code they describe. — [@nikolaydubina](https://github.com/nikolaydubina)

```
go-commentage -min-days-behind 360 ./...
```

Example
```
kubernetes/pkg/util/ipset/ipset.go:283:1: "CreateSet": doc_last_updated_behind_days(1336.83)
kubernetes/pkg/util/ipset/ipset.go:296:1: "createSet": doc_last_updated_behind_days(1603.17)
kubernetes/pkg/util/ipset/ipset.go:320:1: "AddEntry": doc_last_updated_behind_days(1578.10)
kubernetes/pkg/util/ipset/ipset.go:332:1: "DelEntry": doc_last_updated_behind_days(1578.10)
kubernetes/pkg/util/ipset/ipset.go:340:1: "TestEntry": doc_last_updated_behind_days(450.07)
```

Requirements
```


Question: How to: get latest version of git

Answer:
go install github.com/nikolaydubina/go-commentage@latest
```


Question: How to: [⏫](#contents) Ensure `if` statements using short assignment with [ifshort](https://github.com/esimonov/ifshort)

Answer:
Linter for checking that your code uses short syntax for `if` statements whenever possible. However, as of `2023-05-26`, it is not maitaned and is not working. — [@esimonov](https://github.com/esimonov)

```
ifshort ./...
```

```go
// bad
func someFunc(k string, m map[string]interface{}) {
  _, ok := m[k]
  if !ok {
    return
  }

  err := otherFunc1()
  if err != nil {
    otherFunc2(err)
  }
}

// good
func someFunc(k string, m map[string]interface{}) {
  if _, ok := m[k]; !ok {
    return
  }

  if err := otherFunc1(); err != nil {
    otherFunc2(err)
  }
}
```

Requirements
```
go install github.com/esimonov/ifshort@latest
```


Question: How to: [⏫](#contents) Detect sub-optimal struct layout with [betteralign](https://github.com/dkorunic/betteralign)

Answer:
This tool detect structs that would use less memory if their fields were sorted and optionally sort such fields. — [@dkorunic](https://github.com/dkorunic)

```
betteralign -apply ./...
```

Requirements
```
go install github.com/dkorunic/betteralign/cmd/betteralign@latest
```


Question: How to: [⏫](#contents) Detect sub-optimal struct layout with [structlayout-optimize](https://github.com/dominikh/go-tools/blob/master/cmd/structlayout-optimize)

Answer:
This tool reorders struct fields to minimize the amount of padding. — [@dominikh](https://github.com/dominikh)

Requirements
```
go install https://github.com/dominikh/go-tools/blob/master/cmd/structlayout-optimize@latest
```


Question: How to: [⏫](#contents) Visualize struct layout with [structlayout](https://github.com/dominikh/go-tools/tree/master/cmd/structlayout)

Answer:
Display the byte offset and size of each field, respecting alignment/padding. — [@dominikh](https://github.com/dominikh)

```
structlayout -json bytes Buffer | structlayout-svg -t "bytes.Buffer" > /tmp/struct.svg
```
Requirements
```
go install github.com/ajstarks/svgo/structlayout-svg@latest
go install honnef.co/go/tools/cmd/structlayout@latest
```


Question: How to: [⏫](#contents) Rely on compiler for stricter Enums

Answer:
For compile time blocking of: accidental arithmetics; implicit cast of untyped constants; all operators except `==` and `!=`; — simply wrap into a struct in separate package and do not export field. [example](http://github.com/nikolaydubina/go-enum-example).

```go
package color

type Color struct{ c uint }

var (
  Undefined = Color{}
  Red       = Color{1}
  Green     = Color{2}
  Blue      = Color{3}
)
```


Question: How to: [⏫](#contents) Analyze function callsites with [go-callsite-stats](https://github.com/nikolaydubina/go-callsite-stats)

Answer:
Scrape callsite information about functions to learn better how functions are beinn used. This can help in refactoring, naming, OOP. This tool calculates frequency of names on assignments in returns and frequency of names in arguments. This can be used to detect ignored returns as well. — [@nikolaydubina](https://github.com/nikolaydubina)

```
go-callsite-stats ./...
```

```
x16:       (no assignments)                  = execHostnameTest(serviceAddress:7)
                                                              (nodePortAddress:3)
                                                              (nodePortAddress0:3)
                                                              (nodePortAddress1:2)
                                                              (clusterIPAddress:1)
x16:       pod:10, err:12                    = CreatePod(client:11, namespace:10, nil:9, pvclaims:6, false:7, execCommand:2)
          clientPod:1                                  (c:2, ns:2, podCount:2, true:3)
          _:1                                          (pod:1, pod:1, pvclaims:2, false:2)
          err:1                                        (ctx:1, nil:1, createdClaims:1, pvcClaims:1)
                                                        (namespace:1, nameSpace:1, podTemplate:1)
                                                        (, basePod:1)
x16:       (no assignments)                  = GET()
x16:       deployment:11, err:14             = UpdateDeploymentWithRetries(c:14, ns:14, deploymentName:3, applyUpdate:1, poll:1,pollShortTimeout:1)
          _:2                                                            (client:1, namespace:1, pollTimeout:1)
          deploymentWithUpdatedReplicas:1                                (applyUpdate:1, pollInterval:1, name:1)
x16:       err:16                            = waitForDefinition(schemaFoo:12
                                                                (schemaWaldo:3)
                                                                (expect:1)
```

Requirements
```
go install github.com/nikolaydubina/go-callsite-stats@latest
```


Question: How to: Requirements

Answer:
You need to:
-  have [Docker](https://www.docker.com/) installed for your OS;
- [minikube](https://github.com/kubernetes/minikube) installed for running locally; and
- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) installed.


Question: How to: Simple concepts before we start

Answer:
#### What is Docker

Docker is a platform for packaging, distribution and running applications. It allows you to package your application together with its whole environment. This can be either a few libraries that the app requires or even all the files that are usually available on the filesystem of an installed operating system. Docker makes it possible to transfer this package to a central repository from which it can then be transferred to any computer running Docker and executed there.

Three main concepts in Docker comprise this scenario:
- **Images** :— A Docker based container image is something you package your application and its environment. It contains the filesystem that will be available to the application and other metadata, such as the path to the executable that should be executed when the image is run.
- **Registries** :- A Docker Registry is a repository that stores your Docker images and facilitates easy sharing of those images between different users and computers. When you build your image, you can either run it on the computer you’ve built it on, or you can push (upload) the image to a registry and then pull (download) it on another computer and run it there. Certain registries are public, allowing anyone to pull images from it, while others are private, only accessible to certain people or machines.
- **Containers** :- A Docker-based container is a regular Linux container created from a Docker-based container image. A running container is a process running on the host running Docker, but it’s completely isolated from both the host and all other processes running on it. The process is also resource-constrained, meaning it can only access and use the number of resources (CPU, RAM, and so on) that are allocated to it.


Question: How to: Learning while working

Answer:
#### Creating a web server

You first need to create a container image. We will use Docker for that. We are creating a simple web server to see how Kubernetes works.

- create a file `app.js` and copy this code into it

```js
const http = require('http');
const os = require('os');
console.log("Kubia server starting...");
var handler = function (request, response) {
  console.log("Received request from " + request.connection.remoteAddress);
  response.writeHead(200);
  response.end("You've hit " + os.hostname() + "\n");
};
var www = http.createServer(handler);
www.listen(8080);

```

Now we will create a Docker file that will run on a cluster when we create a Docker image.

- Create a file named `Dockerfile` and copy this code into it.

```Dockerfile
FROM node:8

RUN npm i

ADD app.js /app.js

ENTRYPOINT [ "node", "app.js" ]

```

#### Building Docker Image

Make sure your **Docker server is up and running**. Now we will create a Docker image in our local machine. Open your terminal in the current project's folder and run

`docker build -t kubia .`

You’re telling Docker to build an image called **kubia** based on the contents of the current directory (note the dot `.` at the end of the build command). Docker will look for the Dockerfile in the directory and build the image based on the instructions in the file.

Now check your docker image created by running:

`docker images`

#### Getting docker images

`docker images`

This command lists all the images.

#### Running the container image

`docker run --name kubia-container -p 8080:8080 -d kubia`

This tells Docker to run a new container called **kubia-container** from the kubia image. The container will be detached from the console (`-d` flag), which means it will run in the background. `Port 8080` on the local machine will be mapped to `Port 8080` inside the container (`-p 8080:8080` option), so you can access the app through [localhost](http://localhost:8080).

#### Accessing your application

Run in your terminal:

`curl localhost:8080`
> You’ve hit 44d76963e8e1

#### Listing all your running containers

You can list all your running containers with this command.

`docker ps`

The `docker ps` command only shows the most basic information about the containers.

To get additional information about a container, run this command.

`docker inspect kubia-container`

You can see all the containers by running:

`docker ps -a`


Question: How to: Running a shell inside an existing container

Answer:
The Node.js image on which you’ve based your image contains the bash shell, so you can run the shell inside the container like this:

`docker exec -it kubia-container bash`

This will run bash inside the existing **kubia-container** container. The **bash** process will have the same Linux namespaces as the main container process. This allows you to explore the container from within and see how Node.js and your app see the system when running inside the container.

The **`-it`** option is shorthand for two options:

- `-i`, which makes sure STDIN is kept open. You need this for entering commands into the shell.
- `-t`, which allocates a pseudo terminal (TTY).

#### Exploring container from within

Let’s see how to use the shell in the following listing to see the processes running in the container.

```bash
root@c61b9b509f9a:/# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.4  1.3 872872 27832 ?        Ssl  06:01   0:00 node app.js
root        11  0.1  0.1  20244  3016 pts/0    Ss   06:02   0:00 bash
root        16  0.0  0.0  17504  2036 pts/0    R+   06:02   0:00 ps aux
```

You see only three processes. You don’t see any other processes from the host OS.

Like having an isolated process tree, each container also has an isolated filesystem. Listing the contents of the root directory inside the container will only show the files in the container and will include all the files that are in the image plus any files that are created while the container is running (log files and similar), as shown in the following listing.

```bash
root@c61b9b509f9a:/# ls
app.js  bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  package-lock.json  proc  root  run  sbin  srv  sys  tmp  usr  var
```

It contains the **app.js** file and other system directories that are part of the `node:8` base image you’re using.

To exit the container, you exit the shell by running the **exit** command and you’ll be returned to your host machine (like logging out of an ssh session, for example).

#### Stopping and removing a container

`docker stop kubia-container`

This will stop the main process running in the container and consequently stop the container because no other processes are running inside the container. The container itself still exists and you can see it with **docker ps -a**. The `-a` option prints out all the containers, those running and those that have been stopped. To truly remove a container, you need to remove it with the **docker rm** command:

`docker rm kubia-container`

This deletes the container. All its contents are removed and it can’t be started again.


Question: How to: Pushing the image to an image registry

Answer:
The image you’ve built has so far only been available on your local machine. To allow you to run it on any other machine, you need to push the image to an external image registry. For the sake of simplicity, you won’t set up a private image registry and will instead push the image to [Docker Hub](http://hub.docker.com).

Before you do that, you need to re-tag your image according to Docker Hub’s rules. Docker Hub will allow you to push an image if the image’s repository name starts with your Docker Hub ID.

You create your Docker Hub ID by registering at [hub-docker](http://hub.docker.com). I’ll use my own ID (`knrt10`) in the following examples. Please change every occurrence with your own ID.

Once you know your ID, you’re ready to rename your image, currently tagged as `kubia`, to `knrt10/kubia` (replace knrt10 with your own Docker Hub ID):

`docker tag kubia knrt10/kubia`

This doesn’t rename the tag; it creates an additional tag for the same image. You can confirm this by listing the images stored on your system with the Docker images command, as shown in the following listing.

`docker images | head`

As you can see, both `kubia` and `knrt10/kubia` point to the same image ID, so they’re in fact one single image with two tags.

#### Pushing image to docker hub

Before you can push the image to Docker Hub, you need to log in under your user ID with the **docker login** command. Once you’re logged in, you can finally push the `yourid/kubia` image to Docker Hub like this:

`docker push knrt10/kubia`


Question: How to: What is Kubernetes

Answer:
Years ago, most software applications were big `monoliths`, running either as a single process or as a small number of processes spread across a handful of servers.

Today, these big monolithic legacy applications are slowly being broken down into smaller, independently running components called `microservices`.

Because microservices are `decoupled` from each other, they can be developed, deployed, updated, and scaled individually. This enables you to change components quickly and as often as necessary to keep up with today’s rapidly changing business requirements.

But with bigger numbers of deployable components and increasingly larger datacenters, it becomes increasingly difficult to configure, manage, and keep the whole system running smoothly.

It’s much harder to figure out where to put each of those components to achieve high resource utilization and thereby keep the hardware costs down. Doing all this manually is hard work.

We need:

- automation (including automatic scheduling of those components to our servers);
- automatic configuration;
- supervision; and
- failure-handling.

This is where **Kubernetes** comes in.

>
Kubernetes enables developers to deploy their applications themselves and as often as they want, without requiring any assistance from the operations (ops) team.
But Kubernetes doesn’t solely benefit developers. It also helps the ops team by automatically monitoring and rescheduling those apps in the event of a hardware failure.

The focus for system administrators (sysadmins) shifts from supervising individual apps to mostly supervising and managing Kubernetes and the rest of the infrastructure, while Kubernetes itself takes care of the apps.

#### Splitting apps into microservice

Each microservice runs as an independent process and communicates with other microservices through simple, well-defined interfaces (APIs). Refer to the image below:

![Microservice](https://user-images.githubusercontent.com/24803604/68068406-bf4bb200-fd54-11e9-8565-6214d30616bb.png)

>
- Image taken from other source.
Microservices communicate through synchronous protocols such as HTTP, over which they usually expose RESTful (REpresentational State Transfer) APIs, or through asynchronous protocols such as AMQP (Advanced Message Queueing Protocol).

These protocols are simple, well understood by most developers, and not tied to any specific programming language. Each microservice can be written in the language that’s most appropriate for implementing that specific microservice.

Because each microservice is a standalone process with a relatively static external API, it’s possible to develop and deploy each microservice separately. A change to one of them doesn’t require changes or redeployment of any other service, provided that the API doesn’t change or changes only in a backward-compatible way.

#### Scaling Microservices

Scaling microservices, unlike monolithic systems, where you need to scale the system as a whole, is done on a per-service basis, which means you have the option of scaling only those services that require more resources, while leaving others at their original scale. Refer to the image below:

![Scaling](https://user-images.githubusercontent.com/24803604/68068433-03d74d80-fd55-11e9-87fe-5fad885168d1.png)

>
- Image taken from other source.
When a monolithic application can’t be scaled out because one of its parts is unscalable, splitting the app into microservices allows you to horizontally scale the parts that allow scaling out. The parts that don't scale horizontally can be scaled vertically instead.

#### Deploying Microservices

As always, microservices also have drawbacks. When your system consists of only a small number of deployable components, managing those components is easy. It’s trivial to decide where to deploy each component, because there aren’t that many choices.

When the number of those components increases, deployment-related decisions become increasingly difficult because not only does the number of deployment combinations increase, but the number of inter-dependencies between the components increases by an even greater factor.

Microservices also bring other problems, such as making it hard to debug and trace execution calls, because they span multiple processes and machines. Luckily, these problems are now being addressed with distributed tracing systems such as Zipkin.

![Drawback](https://user-images.githubusercontent.com/24803604/68068466-62043080-fd55-11e9-867f-971dc4df862f.png)

>
Multiple applications running on the same host may have conflicting dependencies.
#### Working with Kubernetes

Now that you have your app packaged inside a container image and made available through Docker Hub, you can deploy it in a Kubernetes cluster instead of running it in Docker directly. But first, you need to set up the cluster itself.

#### Setting up a Kubernetes cluster

Setting up a full-fledged, multi-node Kubernetes


Question: How to: Running a local single node Kubernetes cluster with Minikube

Answer:
The simplest and quickest path to a fully functioning Kubernetes cluster is by using Minikube. Minikube is a tool that sets up a single-node cluster that’s great for both testing Kubernetes and developing apps locally.

#### Starting a Kubernetes cluster with minikube

Once you have Minikube installed locally, you can immediately start up the Kubernetes cluster with the following command:

`minikube start`
```bash
Starting local Kubernetes cluster...
Starting VM...
SSH-ing files into VM...
...
Kubectl is now configured to use the cluster.
```

Starting the cluster takes more than a minute, so don’t interrupt the command before
it completes.

#### Checking to see if the cluster is up and Kubernetes can talk to it

To interact with Kubernetes, you also need the **kubectl** CLI client. [Installing](https://kubernetes.io/docs/tasks/tools/install-kubectl/) it is easy.

To verify your cluster is working, you can use the **kubectl cluster-info** command shown in the following listing.

`kubectl cluster-info`
```bash
Kubernetes master is running at https://192.168.99.100:8443

kubernetes-dashboard is running at https://192.168.99.100:8443/api/v1/...

KubeDNS is running at https://192.168.99.100:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
```

This shows the cluster is up. It shows the URLs of the various Kubernetes components, including the API server and the web console.

#### Deploying your Node app

A simple way to deploy your app is to use the **kubectl create** command, which will create all the necessary components without having to deal with JSON or YAML.

`kubectl create deployment kubia --image=knrt10/kubia --port=8080`

The `--image=knrt10/kubia` part obviously specifies the container image you want to run, and the `--port=8080` option tells Kubernetes that your app is listening on port 8080.

#### Listing Pods

Because you can’t list individual containers since they’re not standalone Kubernetes objects, can you list pods instead? Yes, you can. Let’s see how to tell kubectl to list pods in the following listing.

`kubectl get pods`

```bash
$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
kubia-57c4d74858-tflb8   1/1     Running   0          24s
```


Question: How to: Accessing your web application

Answer:
With your pod running, how do you access it? Each pod gets its own IP address, but this address is internal to the cluster and isn’t accessible from outside of it. To make the pod accessible from the outside, you’ll expose it through a Service object.

You’ll create a special service of type LoadBalancer because if you create a regular service (a ClusterIP service), as the pod, it would also only be accessible from inside the cluster. By creating a LoadBalancer-type service, an external load balancer will be created and you can connect to the pod through the load balancer’s public IP.

#### Creating a service object

To create the service, you’ll tell Kubernetes to expose the Deployment you created earlier:

`kubectl expose deploy kubia --type=LoadBalancer --name kubia-http`
> service/kubia-http exposed

**Important:** We’re using the abbreviation `deploy` instead of `deployments`. Most resource types have an abbreviation like this so you don’t have to type the full name (for example, `po` for `pods`, `svc` for `services`, and so on).

#### Listing Services

The expose command’s output mentions a service called `kubia-http`. Services are objects like Pods and Nodes, so you can see the newly created Service object by running the **kubectl get services | svc** command, as shown in the following listing.

`kubectl get svc`

```bash
NAME         TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP      10.96.0.1
443/TCP          30h
kubia-http   LoadBalancer   10.107.88.67
8080:32718/TCP   81s
```

**Important** :- Minikube doesn’t support LoadBalancer services, so the service will never get an external IP. But you can access the service anyway through its external port. So external IP will always be pending in that case. When using Minikube, you can get the IP and port through which you
can access the service by running

`minikube service kubia-http`


Question: How to: Horizontally scaling the application

Answer:
You now have a running application, monitored and kept running by a Deployment and exposed to the world through a service. Now let’s make additional magic happen.
One of the main benefits of using Kubernetes is the simplicity with which you can scale your deployments. Let’s see how easy it is to scale up the number of pods. You’ll increase the number of running instances to three.

Your pod is managed by a Deployment. Let’s see it with the kubectl get command:

`kubectl get deploy`

```bash
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
kubia   1/1     1            1           4m58s
```

#### Increasing the desired Replica count

To scale up the number of replicas of your pod, you need to change the desired replica count in the Deployment like this:

`kubectl scale deploy kubia --replicas=3`
> deployment.apps/kubia scaled

You’ve now told Kubernetes to make sure three instances of your pod are always running. Notice that you didn’t instruct Kubernetes what action to take. You didn’t tell it to add two more pods. You only set the new desired number of instances and let Kubernetes determine what actions it needs to take to achieve the requested state.

#### Seeing the result of the Scale Out

Back to your replica count increase. Let’s list the Deployments again to see the updated replica count:

`kubectl get deploy`

```bash
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
kubia   3/3     3            3           6m43s
```

Because the actual number of pods has already been increased to three (as evident from the CURRENT column), listing all the pods should now show three pods instead of one:

`kubectl get pods`

```bash
NAME                     READY   STATUS    RESTARTS   AGE
kubia-57c4d74858-d284g   1/1     Running   0          94s
kubia-57c4d74858-tflb8   1/1     Running   0          7m9s
kubia-57c4d74858-wfgmb   1/1     Running   0          94s
```

As you can see, three pods exist instead of one. Currently running, but if it is pending, it would be ready in a few moments, as soon as the container image is downloaded and the container is started.

As you can see, scaling an application is incredibly simple. Once your app is running in production and a need to scale the app arises, you can add additional instances with a single command without having to install and run additional copies manually.

Keep in mind that the app itself needs to support being scaled horizontally. Kubernetes doesn’t magically make your app scalable; it only makes it trivial to scale the app up or down.

#### Displaying the Pod IP and Pods Node when listing Pods

If you’ve been paying close attention, you probably noticed that the **kubectl get pods** command doesn’t even show any information about the nodes the pods are scheduled to. This is because it’s usually not an important piece of information.

But you can request additional columns to display using the **-o wide** option. When listing pods, this option shows the pod’s IP and the node the pod is running on:

`kubectl get pods -o wide`

```bash
$ kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP           NODE       NOMINATED NODE   READINESS GATES
kubia-57c4d74858-d284g   1/1     Running   0          2m53s   172.17.0.5   minikube
kubia-57c4d74858-tflb8   1/1     Running   0          8m28s   172.17.0.3   minikube
kubia-57c4d74858-wfgmb   1/1     Running   0          2m53s   172.17.0.4   minikube
```

#### Accessing Dashboard when using Minikube

To open the dashboard in your browser when using Minikube to run your Kubernetes cluster, run the following command:

`minikube dashboard`


Question: How to: Introducing labels

Answer:
Organizing pods and all other Kubernetes objects is done through labels. Labels are a simple, yet incredibly powerful, Kubernetes feature for organizing not only pods, but all other Kubernetes resources. A label is an arbitrary key-value pair you attach to a resource, which is then utilized when selecting resources using label selectors (resources are filtered based on whether they include the label specified in the selector).

#### Specifying labels when creating a pod

Now, you’ll see labels in action by creating a new pod with two labels. Create a new file called **kubia-manual-with-labels.yaml** with the contents of the following listing. You can also copy from [kubia-manual-with-labels.yaml](https://github.com/knrt10/kubernetes-basicLearning/blob/master/kubia-manual-with-labels.yaml)

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: kubia-manual-v2
  labels:
    creation_method: manual
    env: prod
spec:
  containers:
  - image: knrt10/kubia
    name: kubia
    ports:
    - containerPort: 8080
      protocol: TCP
```

You’ve included the labels *creation_method=manual* and *env=data.labels* section. You’ll create this pod now:

`kubectl create -f kubia-manual-with-labels.yaml`
> pod/kubia-manual-v2 created

The **kubectl get po** command doesn’t list any labels by default, but you can see them by using the **--show-labels** switch:

`kubectl get po --show-labels`

```bash
NAME              READY     STATUS    RESTARTS   AGE       LABELS
kubia-5k788       1/1       Running   1          8d        run=kubia
kubia-7zxwj       1/1       Running   1          5d        run=kubia
kubia-bsksp       1/1       Running   1          5d        run=kubia
kubia-manual      1/1       Running   0          7h
kubia-manual-v2   1/1       Running   0          3m        creation_method=manual,env=prod
```

Instead of listing all labels, if you’re only interested in certain labels, you can specify them with the **-L** switch and have each displayed in its own column. List pods again and show the columns for the two labels you’ve attached to your **kubia-manual-v2** pod:

`kubectl get po -L creation_method,env`

#### Modifying labels of existing pods

Labels can also be added to and modified on existing pods. Because the **kubia-manual** pod was also created manually, let’s add the **creation_method=manual** label to it:

`kubectl label po kubia-manual creation_method=manual`

Now, let’s also change the **env=prod** label to **env=debug** on the **kubia-manual-v2** pod, to see how existing labels can be changed. You need to use the **--overwrite** option when changing existing labels.

`kubectl label po kubia-manual-v2 env=debug --overwrite`


Question: How to: Listing subsets of pods through label selectors

Answer:
Attaching labels to resources so you can see the labels next to each resource when listing them isn’t that interesting. But labels go hand in hand with *label selectors*. Label selectors allow you to select a subset of pods tagged with certain labels and perform an operation on those pods.

A label selector can select resources based on whether the resource
- Contains (or doesn’t contain) a label with a certain key
- Contains a label with a certain key and value
- Contains a label with a certain key, but with a value not equal to the one you specify

#### Listing pods using a label selector

Let’s use label selectors on the pods you’ve created so far. To see all pods you created manually (you labeled them with **creation_method=manual**), do the following:

`kubectl get po -l creation_method=manual`
```bash
NAME              READY     STATUS    RESTARTS   AGE
kubia-manual      1/1       Running   0          22h
kubia-manual-v2   1/1       Running   0          14h
```

And those that don’t have the **env** label:

`kubectl get po -l '!env'`
```bash
NAME           READY     STATUS    RESTARTS   AGE
kubia-5k788    1/1       Running   1          9d
kubia-7zxwj    1/1       Running   1          5d
kubia-bsksp    1/1       Running   1          5d
kubia-manual   1/1       Running   0          22h
```

Make sure to use single quotes around **!env**, so the bash shell doesn’t
evaluate the exclamation mark

#### Using multiple conditions in a label selector

A selector can also include multiple comma-separated criteria. Resources need to match all of them to match the selector. You can execute command given below

`kubectl get po -l '!env , !creation_method' --show-labels`


Question: How to: Using labels and selectors to constrain pod scheduling

Answer:
All the pods you’ve created so far have been scheduled pretty much randomly across your worker nodes. Certain cases exist, however, where you’ll want to have at least a little say in where a pod should be scheduled. A good example is when your hardware infrastructure isn’t homogenous. You never want to say specifically what node a pod should be scheduled to, because that would couple the application to the infrastructure, whereas the whole idea of Kubernetes is hiding the actual infrastructure from the apps that run on it.

#### Using labels for categorizing worker nodes

The pods aren't only kubernetes resource type that you can attach label to. Labels can be attached to any Kubernetes resource including nodes.

Let’s imagine one of the nodes in your cluster contains a GPU meant to be used for general-purpose GPU computing. You want to add a label to the node showing this feature. You’re going to add the label **gpu=true** to one of your nodes (pick one out of the list returned by **kubectl get nodes**):

`kubectl label node minikube gpu=true`
> node/minikube labeled

Now you can use a label selector when listing the nodes, like you did before with pods. List only nodes that include the label *gpu=true*:

`kubectl get node -l gpu=true`

```bash
NAME       STATUS    ROLES     AGE       VERSION
minikube   Ready     master    9d        v1.10.0
```

As expected, only one node has this label. You can also try listing all the nodes and tell kubectl to display an additional column showing the values of each node’s gpu label.

`kubectl get nodes -L gpu`
```bash
NAME       STATUS    ROLES     AGE       VERSION   GPU
minikube   Ready     master    9d        v1.10.0   true
```

#### Scheduling pods to specific nodes

Now imagine you want to deploy a new pod that needs a GPU to perform its work. To ask the scheduler to only choose among the nodes that provide a GPU, you’ll add a node selector to the pod’s YAML. Create a file called **kubia-gpu.yaml** with the following listing’s contents and then use **kubectl create -f kubia-gpu.yaml** to create the pod. The contents of file are

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: kubia-gpu
spec:
  nodeSelector:
    gpu: "true"
  containers:
  - image: luksa/kubia
    name: kubia
```

You’ve added a **nodeSelector** field under the spec section. When you create the pod, the scheduler will only choose among the nodes that contain the *gpu=true* label (which is only a single node in your case).

#### Scheduling to one specific node

Similarly, you could also schedule a pod to an exact node, because each node also has a unique label with the key **kubernetes.io/hostname** and value set to the actual hostname of the node. Example shown below

`kubectl get nodes --show-labels`
```bash
NAME       STATUS    ROLES     AGE       VERSION   LABELS
minikube   Ready     master    9d        v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,gpu=true,kubernetes.io/hostname=minikube,node-role.kubernetes.io/master=
```
But setting the *nodeSelector* to a specific node by the hostname label may lead to the pod being unschedulable if the node is offline.


Question: How to: Annotating pods

Answer:
In addition to other labels, pods and other objects can also contain annotations. They are also key value pairs, so in essence they are similar to labels, but aren't meant to hold identifying information. They can't be used to group objects the way label can. While objects can be selected through label selectors, there’s no such thing as an annotation selector. On the other hand, annotations can hold much larger pieces of information and are primarily meant to be used by tools. Certain annotations are automatically added to objects by Kubernetes, but others are added by users manually.

A great use to annotating pods is to add desciption to each pod or other API object so that everyone using the cluster can quickly look up information about each individual object.

#### Looking up an objects annotations

Let’s see an example of an annotation that Kubernetes added automatically to the pod you created in the previous section. To see the annotations, you’ll need to request the full YAML of the pod or use the `kubectl describe` command. You’ll use the first option in the following listing.

`kubectl get po kubia-zb95q -o yaml`
```bash
apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubernetes.io/created-by: |
      {"kind":"SerializedReference", "apiVersion":"v1",
      "reference":{"kind":"ReplicationController", "namespace":"default", ...
```

Without going into too many details, as you can see, the `kubernetes.io/created-by`
annotation holds JSON data about the object that created the pod. That’s not something
you’d want to put into a label. Labels should be **short**, whereas annotations can
contain relatively large blobs of data **(up to 256 KB in total)**.

**Important**:- The kubernetes.io/created-by annotations was deprecated in version
`1.8` and will be removed in `1.9`, so you will no longer see it in the YAML.

#### Adding and modifying annotations

Annotations can obviously be added to pods at creation time, the same way label can. But we can also add it after using the following command. Let's try adding this to `kubia-manual` pod now.

`kubectl annotate pod kubia-manual knrt10.github.io/someannotation="messi ronaldo"`

You added the annotation `knrt10.github.io/someannotation` with the value `messi ronaldo`. It’s a good idea to use this format for annotation keys to prevent key collisions. When different tools or libraries add annotations to objects, they may accidentally override each other’s annotations if they don’t use unique prefixes like you did here. You can check your pod now using following command

`kubectl describe po kubia-manual`


Question: How to: Using namespace to group resources

Answer:
Previously we saw how labels organize pods and objects into groups. Because each object can have multiple labels, those groups of objects can overlap. Plus, when working with the cluster (through kubectl for example), if you don’t explicitly specify a label selector, you’ll always see all objects.

#### Discovering other namespaces and their pods

Let us first list all the namespaces in our cluster, type the following command

`kubectl get ns`
```bash
NAME          STATUS    AGE
default       Active    9h
kube-public   Active    9h
kube-system   Active    9h
```

Up to this point, you’ve operated only in the `default` namespace. When listing resources with the `kubectl get` command, you’ve never specified the namespace explicitly, so kubectl always defaulted to the default namespace, showing you only the objects in that namespace. But as you can see from the list, the kube-public and the kube-system namespaces also exist. Let’s look at the pods that belong to the `kube-system` namespace, by telling kubectl to list pods in that namespace only:

`kubectl get po -n kube-system`
```bash
NAME                                    READY     STATUS    RESTARTS   AGE
etcd-minikube                           1/1       Running   0          4h
kube-addon-manager-minikube             1/1       Running   1          9h
kube-apiserver-minikube                 1/1       Running   0          4h
kube-controller-manager-minikube        1/1       Running   0          4h
kube-dns-86f4d74b45-w8mqv               3/3       Running   4          9h
kube-proxy-25t92                        1/1       Running   0          4h
kube-scheduler-minikube                 1/1       Running   0          4h
kubernetes-dashboard-5498ccf677-2zcw5   1/1       Running   2          9h
storage-provisioner                     1/1       Running   2          9h
```

I will explain about these pods later (don’t worry if the pods shown here
don’t match the ones on your system exactly). It’s clear from the name of the namespace that these are resources related to the Kubernetes system itself. By having them in this separate namespace, it keeps everything nicely organized. If they were all in the default namespace, mixed in with the resources you create yourself, you’d have a hard time seeing what belongs where, and you might inadvertently delete system resources.

Namespaces enable you to separate resources that don’t belong together into nonoverlapping groups. If several users or groups of users are using the same Kubernetes cluster, and they each manage their own distinct set of resources, they should each use their own namespace. This way, they don’t need to take any special care not to inadvertently modify or delete the other users’ resources and don’t need to concern themselves with name conflicts, because namespaces provide a scope for resource names, as has already been mentioned.


Question: How to: Creating a namespace

Answer:
A namespace is a Kubernetes resource like any other, so you can create it by posting a
YAML file to the Kubernetes API server. Let’s see how to do this now.

You’re going to create a file called **custom-namespace.yaml** (you can create it in any directory you want), or copy from this repo, where you’ll find the file with filename [custom-namespace.yaml](https://github.com/knrt10/kubernetes-basicLearning/blob/master/custom-namespace.yaml). The following listing shows the entire contents of the file.

```yml
apiVersion: v1
kind: Namespace
metadata:
  name: custom-namespace
```

Now type the following command

`kubectl create -f custom-namespace.yaml`
> namespace/custom-namespace created

#### Managing objects in other namespaces

To create resources in the namespace you’ve created, either add a `namespace: customnamespace` entry to the metadata section, or specify the namespace when creating the resource with the `kubectl create` command:

`kubectl create -f kubia-manual.yaml -n custom-namespace`
> pod/kubia-manual created

You now have two pods with the same name (kubia-manual). One is in the `default`
namespace, and the other is in your `custom-namespace`.

When listing, describing, modifying, or deleting objects in other namespaces, you
need to pass the `--namespace (or -n)` flag to kubectl. If you don’t specify the namespace, kubectl performs the action in the default namespace configured in the current kubectl context. The current context’s namespace and the current context itself can be changed through `kubectl config` commands.

#### Understanding the isolation provided by namespaces

To wrap up this section about namespaces, let me explain what namespaces don’t provide at least not out of the box. Although namespaces allow you to isolate objects into distinct groups, which allows you to operate only on those belonging to the specified namespace, they don’t provide any kind of isolation of running objects. For example, you may think that when different users deploy pods across different namespaces, those pods are isolated from each other and can’t communicate but that’s not necessarily the case. Whether namespaces provide network isolation depends on which networking solution is deployed with Kubernetes. When the solution doesn’t provide inter-namespace network isolation, if a pod in namespace foo knows the IP address of a pod in namespace bar, there is nothing preventing it from sending traffic, such as HTTP requests, to the other pod.


Question: How to: Stopping and removing pods

Answer:
We have created a number of pods which should all be running. If you have followed from the start, you should have 5 pods in `default` namespace and one in `custom-namespace`. We are going to stop them all now, because we don't need them anymore.

#### Deleting a pod by name

Let's first delete `kubia-gpu` pod name

`kubectl delete po kubia-gpu`

#### Deleting pods using label selectors

Instead of specifying each pod to delete by name, you’ll now use what you’ve learned
about label selectors to stop both the `kubia-manual` and the `kubia-manual-v2` pod.
Both pods include the `creation_method=manual` label, so you can delete them by
using a label selector:

`kubectl delete po -l creation_method=manual`
> pod "kubia-manual" deleted
> pod "kubia-manual-v2" deleted

In the earlier microservices example, where you had tens (or possibly hundreds) of
pods, you could, for instance, delete all canary pods at once by specifying the
`rel=canary` label selector

`kubectl delete po -l rel=canary`

#### Deleting pods by deleting the whole namespace

Okay, back to your real pods. What about the pod in the `custom-namespace`? We no
longer need either the pods in that namespace, or the namespace itself. You can delete the whole namespace using the following command. Your all pods inside that workspace will be automatically deleted.

`kubectl delete ns custom-namespace`
> namespace "custom-namespace" deleted

#### Deleting all pods in namespace, while keeping the namespace

Suppose you want to keep your namespace but delete all the pods in it, so this is the approach to follow. We now have cleaned almost everything but we have some pods running if you ran the `kubectl run` command before.

This time, instead of deleting the specific pod, tell Kubernetes to delete all pods in the current namespace by using the --all option

`kubectl delete po --all`
```bash
pod "kubia-pjxrs" deleted
pod "kubia-xvfxp" deleted
pod "kubia-zb95q" deleted
```

Now, double check that no pods were left running:

`kubectl get po`
```bash
kubia-5gknm   1/1       Running   0          48s
kubia-h62k7   1/1       Running   0          48s
kubia-x4nsb   1/1       Running   0          48s
```

Wait, what!?! All pods are terminating, but a new pod which weren't there before, has appeared. No matter how many times you delete all pods, a new pod called kubia-something will emerge.

You may remember you created your first pod with the `kubectl run` command. I mentioned that this doesn’t create a pod directly, but instead creates a `ReplicationController`, which then creates the pod. As soon as you delete a pod created by the ReplicationController, it immediately creates a new one. To delete the pod, you also need to **delete the ReplicationController**.

#### Delete almost all resources in namespace

You can delete the ReplicationController and the pods, as well as all the Services
you’ve created, by deleting all resources in the current namespace with a single
command:

`kubectl delete all --all`
```bash
pod "kubia-5gknm" deleted
pod "kubia-h62k7" deleted
pod "kubia-x4nsb" deleted
replicationcontroller "kubia" deleted
service "kubernetes" deleted
service "kubia-http" deleted
```

The first all in the command specifies that you’re deleting resources of all types, and the --all option specifies that you’re deleting all resource instances instead of specifying them by name (you already used this option when you ran the previous delete command).

As it deletes resources, kubectl will print the name of every resource it deletes. In the list, you should see the kubia ReplicationController and the `kubia-http` Service you created before.

**Note**:- The kubectl delete all --all command also deletes the kubernetes
Service, but it should be recreated automatically in a few moments.


Question: How to: Introducing ReplicationControllers

Answer:
A Replication Controller(RC) is a Kubernetes resource that ensures its pods are always kept running. If a pod disappers for any reasons like in case of node disappearing from the cluster or because the pod was evicted from the node, the RC notes the pod missing and creates a replacement pod. Please refer to the image below

![RC](https://user-images.githubusercontent.com/24803604/70711851-6c2c2e00-1d08-11ea-90cd-1feba139645d.png)

> When a node fails, only pods backed by a ReplicationController are recreated.

The RC in the figure only manage only a single pod but in general they are meant to create and manage a mutiple copies (replicas) of a pod. That's where RC got their name from.

#### The operation of a ReplicationController

The RC contantly monitors the list of running pods and makes sure the actual number of pods of a "type" always matches the desires number. If too few such pods are running, it creates new replica from pod template. If too much pods are running, it remove the excess replicas.

You might be wondering how there can be more than the desired number of replicas. This can happen for a few reasons:

- Someone creates a pod of the same type manually.
- Someone changes an existing pod’s “type.”
- Someone decreases the desired number of pods, and so on.

I’ve used the term pod “type” a few times. But no such thing exists. Replication Controllers don’t operate on pod types, but on sets of pods that match a certain label selector, which I have told you previously.

#### Introducing the controller reconciliation loop

A ReplicationController’s job is to make sure that an exact number of pods always matches its label selector. If it doesn’t, the ReplicationController takes the appropriate action to reconcile the actual with the desired number.

![controller-reconcilition-loop](https://user-images.githubusercontent.com/24803604/70713322-c5e22780-1d0b-11ea-9334-3d9213e86d3c.png)

A ReplicationController has three essential parts:

- A label selector, which determines what pods are in the ReplicationController’s scope
- A replica count, which specifies the desired number of pods that should be running
- A pod template, which is used when creating new pod replicas

![RC three parts](https://user-images.githubusercontent.com/24803604/70715546-8964fa80-1d10-11ea-8e33-59f1a5a36698.png)

> The three key parts of a
ReplicationController (pod selector,
replica count, and pod template)

A ReplicationController’s replica count, the label selector, and even the pod template can all be modified at any time, but only changes to the replica count affect existing pods.

Changes to the label selector and the pod template have no effect on existing pods. Changing the label selector makes the existing pods fall out of the scope of the ReplicationController, so the controller stops caring about them. ReplicationControllers also don’t care about the actual “contents” of its pods (the container images, environment variables, and other things) after they create the pod. The template therefore only affects new pods created by this ReplicationController. You can think of it as a cookie cutter for cutting out new pods.

**BENEFITS**

- It makes sure a pod (or multiple pod replicas) is always running by starting a
new pod when an existing one goes missing.
- When a cluster node fails, it creates replacement replicas for all the pods that
were running on the failed node (those that were under the Replication-
Controller’s control).
- It enables easy horizontal scaling of pods—both manual and automatic

**Note**:- A pod instance is never relocated to another node. Instead, the ReplicationController creates a completely new pod instance that has no relation to the instance it’s replacing.

#### Creating a ReplicationController

You’re going to create a file called **kubia-rc.yaml** (you can create it in any directory you want), or copy from this repo, where you’ll find the file with filename [kubia-rc.yaml](https://github.com/knrt10/kubernetes-basicLearning/blob/master/kubia-rc.yaml). The following listing shows the entire contents of the file.

```yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: kubia
spec:
  replicas: 3
  selector:
    app: kubia
  template:
    metadata:
      labels:
        app: kubia
    spec:
      containers:
      - name: kubia
        image: knrt10/kubia
        ports:
        - containerPort: 8080
```

When you post the file to the API server, Kubernetes creates a new ReplicationController named `kubia`, which makes sure three pod instances always match the label selector `app=kubia`. When there aren’t enough pods, new pods will be created from the provided pod template. The contents of the template are almost identical to pod defination we created before.

The pod labels in the template must obviously match the label selector of the ReplicationController; otherwise the controller would create new pods indefinitely, because spinning up a new pod wouldn’t bring the actual replica co


Question: How to: Using ReplicaSets instead of ReplicationControllers

Answer:
Initially, ReplicationControllers were the only Kubernetes component for replicating pods and rescheduling them when nodes failed. Later, a similar resource called a ReplicaSet was introduced. It’s a new generation of ReplicationController and replaces it completely (ReplicationControllers will eventually be deprecated).

We could have started this section by creating a ReplicaSet instead of a ReplicationController, but I felt it would be a good idea to start with what was initially available in Kubernetes **(Please Don't report me :wink:)**. Plus, we'll still see ReplicationControllers used in the wild, so it’s good for you to know about them. That said, you should always create ReplicaSets instead of ReplicationControllers from now on. They’re almost identical, so you shouldn’t have any trouble using them instead.

A ReplicaSet behaves exactly like a ReplicationController, but it has more expressive pod selectors. Whereas a ReplicationController’s label selector only allows matching pods that include a certain label, a ReplicaSet’s selector also allows matching pods that lack a certain label or pods that include a certain label key, regardless of its value.

Also, for example, a single ReplicationController can’t match pods with the label `env=production` and those with the label `env=devel` at the same time. It can only match either pods with the env=production label or pods with the env=devel label. But a single ReplicaSet can match both sets of pods and treat them as a single group.

Similarly, a ReplicationController can’t match pods based merely on the presence of a label key, regardless of its value, whereas a ReplicaSet can. For example, a ReplicaSet can match all pods that include a label with the key env, whatever its actual value is(you can think of it as env=*).

#### Defining a ReplicaSet

You’re going to create a ReplicaSet now to see how the orphaned pods that were created by your ReplicationController and then abandoned earlier can now be adopted by a ReplicaSet.

You’re going to create a file called **kubia-replicaset.yaml** (you can create it in any directory you want), or copy from this repo, where you’ll find the file with filename [kubia-replicaset.yaml](https://github.com/knrt10/kubernetes-basicLearning/blob/master/kubia-replicaset.yaml). The following listing shows the entire contents of the file.

```yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: kubia
spec:
  replicas: 3
  selector:
    matchLabels:
      app: kubia
  template:
    metadata:
      labels:
        app: kubia
    spec:
      containers:
      - name: kubia
        image: knrt10/kubia
        ports:
        - containerPort: 8080
```

The first thing to note is that ReplicaSets aren’t part of the v1 API, so you need to ensure you specify the proper apiVersion when creating the resource. You’re creating a resource of type ReplicaSet which has much the same contents as the ReplicationController you created earlier.

The only difference is in the selector. Instead of listing labels the pods need to have directly under the selector property, you’re specifying them under selector `matchLabels`. This is the simpler (and less expressive) way of defining label selectors in a ReplicaSet. Because you still have three pods matching the app=kubia selector running from earlier, creating this ReplicaSet will not cause any new pods to be created. The ReplicaSet will take those existing three pods under its wing. You can create ReplicaSet using `kubectl create` command. Then examine using `kubectl describe` command.

As you can see, the ReplicaSet isn’t any different from a ReplicationController. It’s showing it has three replicas matching the selector. If you list all the pods, you’ll see they’re still the same three pods you had before. The ReplicaSet didn’t create any new ones.

#### Using the ReplicaSets more expressive label selectors

The main improvements of ReplicaSets over ReplicationControllers are their more expressive label selectors. You intentionally used the simpler matchLabels selector in the first ReplicaSet example to see that ReplicaSets are no different from ReplicationControllers.

You can add additional expressions to the selector. As in the example, each expression must contain a key, an operator, and possibly (depending on the operator) a list of values. You’ll see four valid operators:

- `In`—Label’s value must match one of the specified values.
- `NotIn`—Label’s value must not match any of the specified values.
- `Exists`—Pod must include a label with the specified key (the value isn’t important).
When using this operator, you shouldn’t specify the values field.
- `DoesNotExist`—Pod must not include a label with the specified key. The values
property must not be specified.

If you specify multiple expressions, all those expressions must evaluate to true for the selector to match a pod. If you specify both matchLabels and matchExpressions, all the labels must match and all the expressions must


Question: How to: Running exactly one pod on each node with DaemonSets

Answer:
Both RC and RS are used for running specifics number of pods deployed anywhere in Kubernetes cluster. But certain cases exist when you want a pod to run on each and every node in the cluster (and each node needs to run exactly one instance of the pod). Those cases include infrastructure related pods that perform system-level operations.

For example, you’ll want to run a log collector and a resource monitor on every node. Another good example is Kubernetes’ own kube-proxy process, which needs to run on all nodes to make services work.

![Daemon Sets](https://user-images.githubusercontent.com/24803604/71682868-9183e900-2d56-11ea-9cab-e645ef0564b1.png)

> DaemonSets run only a single pod replica on each node, whereas ReplicaSets scatter them around the whole cluster randomly.

#### Using a DaemonSet to run a pod on every node

To run a pod on all cluster nodes, you create a DaemonSet object, which is much like a ReplicationController or a ReplicaSet, except that pods created by a DaemonSet already have a target node specified and skip the Kubernetes Scheduler. They aren’t scattered around the cluster randomly.

A DaemonSet makes sure it creates as many pods as there are nodes and deploys each one on its own node, as shown above. Whereas a ReplicaSet (or ReplicationController) makes sure that a desired number of pod replicas exist in the cluster, a DaemonSet doesn’t have any notion of a desired replica count. It doesn’t need it because its job is to ensure that a pod matching its pod selector is running on each node.

If a node goes down, the DaemonSet doesn’t cause the pod to be created elsewhere. But when a new node is added to the cluster, the DaemonSet immediately deploys a new pod instance to it. It also does the same if someone inadvertently deletes one of the pods, leaving the node without the DaemonSet’s pod. Like a ReplicaSet, a DaemonSet creates the pod from the pod template configured in it.

#### Explaning Daemon sets with an example

Let’s imagine having a daemon called `ssd-monitor` that needs to run on all nodes that contain a solid-state drive (SSD). You’ll create a DaemonSet that runs this daemon on all nodes that are marked as having an SSD. The cluster administrators have added the `disk=ssd` label to all such nodes, so you’ll create the DaemonSet with a node selector that only selects nodes with that label,

![creating daemon sets](https://user-images.githubusercontent.com/24803604/71683593-9c3f7d80-2d58-11ea-94a0-ffc9c3cd4071.png)

You’ll create a DaemonSet that runs a mock ssd-monitor process, which prints "SSD OK" to the standard output every five seconds. I’ve already prepared the mock container image and pushed it to Docker Hub, so you can use it instead of building your own.

You’re going to create a file called **ssd-monitor-daemonset.yaml** (you can create it in any directory you want), or copy from this repo, where you’ll find the file with filename [ssd-monitor-daemonset.yaml](https://github.com/knrt10/kubernetes-basicLearning/blob/master/ssd-monitor-daemonset.yaml). The following listing shows the entire contents of the file.

```yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: ssd-monitor
spec:
  selector:
    matchLabels:
      app: ssd-monitor
  template:
    metadata:
      labels:
        app: ssd-monitor
    spec:
      nodeSelector:
        disk: ssd
      containers:
      - name: main
        image: knrt10/ssd-monitor
```

You’re defining a DaemonSet that will run a pod with a single container based on the `knrt10/ssd-monitor` container image. An instance of this pod will be created for each node that has the `disk=ssd` label.

#### Creating the DaemonSet

Use `kubectl create` command as you know.

`kubectl create -f ssd-monitor-daemonset.yaml`

Let’s see the created DaemonSet:

`kubectl get ds`

```bash
NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
ssd-monitor   0         0         0       0            0           disk=ssd        18s
```

Those zeroes look strange. Didn’t the DaemonSet deploy any pods? List the pods:

`kubectl get po`
> No resources found.

Where are the pods? Do you know what’s going on? Yes, you forgot to label your nodes with the disk=ssd label. No problem—you can do that now. The DaemonSet should detect that the nodes’ labels have changed and deploy the pod to all nodes with a matching label. Let’s see if that’s true. The DaemonSet should have created one pod now. Let’s see:

`kubectl label node minikube disk=ssd`

```bash
NAME                READY   STATUS    RESTARTS   AGE
ssd-monitor-zs6sr   1/1     Running   0          6s
```

Okay; so far so good. If you have multiple nodes and you add the same label to further nodes, you’ll see the DaemonSet spin up pods for each of them. Now, imagine you’ve made a mistake and have mislabeled one of the nodes. It has a spinning disk drive, not an SSD. What happens if you change the node’s label?

The pod is being terminated. But you knew that was going to happ