Skip to content

Instantly share code, notes, and snippets.

View jpbetz's full-sized avatar

Joe Betz jpbetz

  • Google
  • Annapolis, MD
View GitHub Profile
@jpbetz
jpbetz / _REPRODUCTION.md
Last active March 8, 2024 18:19
CRD with invalid conversion webhook CRBundle fails on reads and writes for versions not requiring conversion

What happens:

Create a mult-version CRD with a conversion webhook configured with an invalid CABundle:

$ kubectl apply -f crd.yaml
customresourcedefinition.apiextensions.k8s.io/replicant.stable.example.com created

Read the CRD back:

# config for 1 control plane node and 2 workers (necessary for conformance)
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
ipFamily: ipv4
kubeProxyMode: iptables
# don't pass through host search paths
# TODO: possibly a reasonable default in the future for kind ...
dnsSearch: []
nodes:
# KEP Authors
echo keps/*/*/kep.yaml | xargs -n 1 yq "select(.status == \"implemented\" or .status == \"implementable\") | .authors[]" | sort | uniq -c | sort -n
# KEP Reviewers
echo keps/*/*/kep.yaml | xargs -n 1 yq "select(.status == \"implemented\" or .status == \"implementable\") | .reviewers[]" | sort | uniq -c | sort -n
# KEP Approvers

Problem

Kubernetes generateName randomly generates a 5 char sequence that is appended as a "hash" to the generateName prefix (spoiler: It's not really a hash, just an encoded random number).

Each char in the sequence is from the "bcdfghjklmnpqrstvwxz2456789" range.

This leads to $27^5 = 14,348,907$ possible names per generateName prefix. For context, we have seen clusters store 100,000..1,000,000 CRDs, so the total number of names that can be generated is not currently a problem.

But there is a problem with collisions. There is a 50% chance of hitting a collision before generating even 5000 names, and a 0.1% chance at only 500 names!

@jpbetz
jpbetz / gist:a093890823259f65d47471df668ec0a6
Last active February 9, 2024 15:20
Stability level of SIG api-machinery KEPs as of 2023-10-05
echo keps/sig-api-machinery/*/kep.yaml | xargs -n 1 yq 'select(.stage=="alpha" and .status =="implementable") | .title'
Union types
Migrating API objects to latest storage version
Graduate Server-side Get and Partial Objects to GA
OwnerReference Resource Field
Consistent Reads from Cache
Publish versioning information in OpenAPI
OpenAPI Enum Types
Transition from SPDY to Websockets
CRD Validation Ratcheting
@jpbetz
jpbetz / readme.md
Last active August 22, 2023 17:27
How emulate other architectures (ppc64le, arm64) to test Kubernetes code

First, install podman and buildah. These tools support running containers build for other architectures like arm64 and ppc64le.

Next, create a Dockerfile, e.g.:

FROM ppc64le/golang:1.20.7-alpine
ADD kubernetes /kubernetes

Note that this dockerfile is for ppc64le, so can't be run directly with docker on an amd64 linux machine.

@jpbetz
jpbetz / comparison.md
Last active August 22, 2023 02:46
Comparison of ppc64le and amd64 for Kubernetes #119800 issue (after fix)
case "replace":
		if target != nil && len(args) >= 2 {
			sz := l.sizeEstimate(*target)
			toReplaceSz := l.sizeEstimate(args[0])
			if toReplaceSz.Min == 0 {
				toReplaceSz.Min = 1 // replace will replace each char with the replacement if an empty "to replace" string is given
			}
			replaceWithSz := l.sizeEstimate(args[1])
			fmt.Printf("replace sz: %v\n", sz)
@jpbetz
jpbetz / comparison.md
Last active August 22, 2023 02:46
Comparison of ppc64le and amd64 for Kubernetes #119800 issue
              case "replace":                                                                                                             
                if target != nil && len(args) >= 2 {                                                                                
                        sz := l.sizeEstimate(*target)                                                                               
                        toReplaceSz := l.sizeEstimate(args[0])                                                                      
                        replaceWithSz := l.sizeEstimate(args[1])                                                                    
                        fmt.Printf("replace sz: %v\n", sz)                                                                          
                        fmt.Printf("toReplaceSz: %v\n", toReplaceSz)                                                                
                        fmt.Printf("replaceWithSz: %v\n", replaceWithSz)           
@jpbetz
jpbetz / regex-validity.md
Created August 3, 2023 15:04
Check regex validity with CEL
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: regextests.stable.example.com
spec:
  group: stable.example.com
  versions:
    - name: v1
      served: true
// ValidFieldPath validates that jsonPath is a valid JSON Path containing only field and map accessors
// that are valid for the given schema, and returns a field.Path representation of the validated jsonPath or an error.
func ValidFieldPath(jsonPath string, schema *schema.Structural) (validFieldPath *field.Path, err error) {
appendToPath := func(name string) error {
if schema.AdditionalProperties != nil {
validFieldPath = validFieldPath.Key(name)
schema = schema.AdditionalProperties.Structural
} else if schema.Properties != nil {
validFieldPath = validFieldPath.Child(name)