100% found this document useful (5 votes)
39 views

Instant ebooks textbook (Ebook) Kubernetes Programming with Go: Programming Kubernetes Clients and Operators Using Go and the Kubernetes API by Philippe Martin ISBN 9781484290255, 1484290259 download all chapters

The document provides information about various ebooks related to Kubernetes and programming with Go, including titles, authors, and ISBNs. It highlights the availability of digital formats for instant download and includes a detailed table of contents for the book 'Kubernetes Programming with Go' by Philippe Martin. Additionally, it mentions copyright information and resources for supplementary materials related to the book.

Uploaded by

zuccollanoo1
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (5 votes)
39 views

Instant ebooks textbook (Ebook) Kubernetes Programming with Go: Programming Kubernetes Clients and Operators Using Go and the Kubernetes API by Philippe Martin ISBN 9781484290255, 1484290259 download all chapters

The document provides information about various ebooks related to Kubernetes and programming with Go, including titles, authors, and ISBNs. It highlights the availability of digital formats for instant download and includes a detailed table of contents for the book 'Kubernetes Programming with Go' by Philippe Martin. Additionally, it mentions copyright information and resources for supplementary materials related to the book.

Uploaded by

zuccollanoo1
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 81

Download the Full Ebook and Access More Features - ebooknice.

com

(Ebook) Kubernetes Programming with Go:


Programming Kubernetes Clients and Operators Using
Go and the Kubernetes API by Philippe Martin ISBN
9781484290255, 1484290259
https://ebooknice.com/product/kubernetes-programming-with-
go-programming-kubernetes-clients-and-operators-using-go-
and-the-kubernetes-api-47434838

OR CLICK HERE

DOWLOAD EBOOK

Download more ebook instantly today at https://ebooknice.com


Instant digital products (PDF, ePub, MOBI) ready for you
Download now and discover formats that fit your needs...

Start reading on any device today!

(Ebook) Kubernetes Programming with Go: Programming


Kubernetes Clients and Operators Using Go and the
Kubernetes API by Philippe Martin ISBN 9781484290262,
1484290267
https://ebooknice.com/product/kubernetes-programming-with-go-
programming-kubernetes-clients-and-operators-using-go-and-the-
kubernetes-api-47556106
ebooknice.com

(Ebook) Kubernetes Operators by Jason Dobies and Joshua


Wood

https://ebooknice.com/product/kubernetes-operators-49849748

ebooknice.com

(Ebook) Kubernetes: Preparing for the CKA and CKAD


Certifications by Martin, Philippe ISBN 9781484264942,
1484264940
https://ebooknice.com/product/kubernetes-preparing-for-the-cka-and-
ckad-certifications-29874148

ebooknice.com

(Ebook) gRPC: Up and Running: Building Cloud Native


Applications with Go and Java for Docker and Kubernetes by
Kasun Indrasiri, Danesh Kuruppu ISBN 9781492058335,
1492058335, B0845YMM37
https://ebooknice.com/product/grpc-up-and-running-building-cloud-
native-applications-with-go-and-java-for-docker-and-
kubernetes-10690006
ebooknice.com
(Ebook) Go Systems Programming: Master Linux and Unix
system level programming with Go by Mihalis Tsoukalos ISBN
9781787125643, 1787125645
https://ebooknice.com/product/go-systems-programming-master-linux-and-
unix-system-level-programming-with-go-7206744

ebooknice.com

(Ebook) Kubernetes Operators by Jason Dobies, Joshua Wood


ISBN 9781492048053, 1492048054

https://ebooknice.com/product/kubernetes-operators-10842206

ebooknice.com

(Ebook) Programming Kubernetes: Developing Cloud-Native


Applications by Michael Hausenblas, Stefan Schimanski ISBN
9781492047100, 1492047104
https://ebooknice.com/product/programming-kubernetes-developing-cloud-
native-applications-10443412

ebooknice.com

(Ebook) Kubernetes for Serverless Applications: Implement


FaaS by Effectively Deploying, Managing, Monitoring, and
Orchestrating Serverless Applications Using Kubernetes by
Russ McKendrick ISBN 9781788626125, 1788626125
https://ebooknice.com/product/kubernetes-for-serverless-applications-
implement-faas-by-effectively-deploying-managing-monitoring-and-
orchestrating-serverless-applications-using-kubernetes-51982494
ebooknice.com

(Ebook) Ansible for Kubernetes by Example: Automate Your


Kubernetes Cluster with Ansible by Luca Berton ISBN
9781484292853, 1484292855
https://ebooknice.com/product/ansible-for-kubernetes-by-example-
automate-your-kubernetes-cluster-with-ansible-50105068

ebooknice.com
Kubernetes Programming
with Go
Programming Kubernetes Clients
and Operators Using
Go and the Kubernetes API

Philippe Martin
Kubernetes Programming with Go: Programming Kubernetes Clients and Operators
Using Go and the Kubernetes API

Philippe Martin
Blanquefort, France

ISBN-13 (pbk): 978-1-4842-9025-5 ISBN-13 (electronic): 978-1-4842-9026-2


https://doi.org/10.1007/978-1-4842-9026-2

Copyright © 2023 by Philippe Martin


This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the
material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation,
broadcasting, reproduction on microfilms or in any other physical way, and transmission or information
storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now
known or hereafter developed.
Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol with
every occurrence of a trademarked name, logo, or image we use the names, logos, and images only in an
editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the
trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are not
identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to
proprietary rights.
While the advice and information in this book are believed to be true and accurate at the date of publication,
neither the authors nor the editors nor the publisher can accept any legal responsibility for any errors or
omissions that may be made. The publisher makes no warranty, express or implied, with respect to the
material contained herein.
Managing Director, Apress Media LLC: Welmoed Spahr
Acquisitions Editor: Divya Modi
Development Editor: James Markham
Coordinating Editor: Divya Modi
Copy Editor: Kim Burton Wiseman
Cover designed by eStudioCalamar
Cover image designed by Freepik (www.freepik.com)
Distributed to the book trade worldwide by Springer Science+Business Media New York, 1 New York Plaza,
New York, NY 10004. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail [email protected], or
visit www.springeronline.com. Apress Media, LLC is a California LLC and the sole member (owner) is
Springer Science + Business Media Finance Inc (SSBM Finance Inc). SSBM Finance Inc is a Delaware
corporation.
For information on translations, please e-mail [email protected]; for reprint,
paperback, or audio rights, please e-mail [email protected].
Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook versions and
licenses are also available for most titles. For more information, reference our Print and eBook Bulk Sales
web page at http://www.apress.com/bulk-sales.
Any source code or other supplementary material referenced by the author in this book is available to readers
on GitHub via the book's product page, located at https://github.com/Apress/Kubernetes-Programming-
with-Go-by-Philippe-Martin. For more detailed information, please visit http://www.apress.com/
source-code.
Printed on acid-free paper
To Mélina and Elsa, my constant source of truth
Table of Contents
About the Author��������������������������������������������������������������������������������������������������� xiii

About the Technical Reviewers�������������������������������������������������������������������������������xv


Acknowledgments�������������������������������������������������������������������������������������������������xvii

Introduction������������������������������������������������������������������������������������������������������������xix

Chapter 1: Kubernetes API Introduction������������������������������������������������������������������� 1


Kubernetes Platform at a Glance�������������������������������������������������������������������������������������������������� 1
OpenAPI Specification������������������������������������������������������������������������������������������������������������������� 3
Verbs and Kinds���������������������������������������������������������������������������������������������������������������������������� 5
Group-Version-Resource��������������������������������������������������������������������������������������������������������������� 6
Sub-resources������������������������������������������������������������������������������������������������������������������������������ 8
Official API Reference Documentation������������������������������������������������������������������������������������������ 9
The Deployment Documentation������������������������������������������������������������������������������������������� 10
Operations Documentation���������������������������������������������������������������������������������������������������� 12
The Pod Documentation�������������������������������������������������������������������������������������������������������� 14
One-Page Version of the Documentation������������������������������������������������������������������������������� 15
Conclusion���������������������������������������������������������������������������������������������������������������������������������� 16

Chapter 2: Kubernetes API Operations������������������������������������������������������������������� 17


Examining Requests������������������������������������������������������������������������������������������������������������������� 17
Making Requests������������������������������������������������������������������������������������������������������������������������ 18
Using kubectl as a Proxy������������������������������������������������������������������������������������������������������� 18
Creating a Resource�������������������������������������������������������������������������������������������������������������� 19
Getting Information About a Resource����������������������������������������������������������������������������������� 20
Getting the List of Resources������������������������������������������������������������������������������������������������ 20

v
Table of Contents

Filtering the Result of a List�������������������������������������������������������������������������������������������������� 21


Deleting a Resource�������������������������������������������������������������������������������������������������������������� 26
Deleting a Collection of Resources���������������������������������������������������������������������������������������� 26
Updating a Resource������������������������������������������������������������������������������������������������������������� 27
Managing Conflicts When Updating a Resource�������������������������������������������������������������������� 28
Using a Strategic Merge Patch to Update a Resource����������������������������������������������������������� 32
Applying Resources Server-side�������������������������������������������������������������������������������������������� 38
Watching Resources�������������������������������������������������������������������������������������������������������������� 44
Filtering During a Watch Session������������������������������������������������������������������������������������������� 45
Watching After Listing Resources������������������������������������������������������������������������������������������ 45
Restarting a watch Request�������������������������������������������������������������������������������������������������� 46
Allowing Bookmarks to Efficiently Restart a watch Request������������������������������������������������� 47
Paginating Results����������������������������������������������������������������������������������������������������������������� 50
Getting Results in Various Formats��������������������������������������������������������������������������������������������� 52
Getting Results as a Table����������������������������������������������������������������������������������������������������� 52
Using the YAML Format��������������������������������������������������������������������������������������������������������� 54
Using the Protobuf Format���������������������������������������������������������������������������������������������������� 54
Conclusion���������������������������������������������������������������������������������������������������������������������������������� 55

Chapter 3: Working with API Resources in Go�������������������������������������������������������� 57


API Library Sources and Import�������������������������������������������������������������������������������������������������� 57
Content of a Package������������������������������������������������������������������������������������������������������������������ 58
types.go��������������������������������������������������������������������������������������������������������������������������������� 58
register.go������������������������������������������������������������������������������������������������������������������������������ 59
doc.go������������������������������������������������������������������������������������������������������������������������������������ 60
generated.pb.go and generated.proto����������������������������������������������������������������������������������� 60
types_swagger_doc_generated.go��������������������������������������������������������������������������������������� 60
zz_generated.deepcopy.go���������������������������������������������������������������������������������������������������� 61
Specific Content in core/v1��������������������������������������������������������������������������������������������������������� 61
ObjectReference�������������������������������������������������������������������������������������������������������������������� 61
ResourceList�������������������������������������������������������������������������������������������������������������������������� 62
Taint��������������������������������������������������������������������������������������������������������������������������������������� 64

vi
Table of Contents

Toleration������������������������������������������������������������������������������������������������������������������������������� 65
Well-Known Labels���������������������������������������������������������������������������������������������������������������� 66
Writing Kubernetes Resources in Go������������������������������������������������������������������������������������������ 67
Importing the Package���������������������������������������������������������������������������������������������������������� 67
The TypeMeta Fields�������������������������������������������������������������������������������������������������������������� 68
The ObjectMeta Fields����������������������������������������������������������������������������������������������������������� 69
Spec and Status�������������������������������������������������������������������������������������������������������������������� 76
Comparison with Writing YAML Manifests����������������������������������������������������������������������������� 76
A Complete Example������������������������������������������������������������������������������������������������������������������� 78
Conclusion���������������������������������������������������������������������������������������������������������������������������������� 83

Chapter 4: Using Common Types���������������������������������������������������������������������������� 85


Pointers��������������������������������������������������������������������������������������������������������������������������������������� 85
Getting the Reference of a Value������������������������������������������������������������������������������������������� 85
Dereferencing a Pointer��������������������������������������������������������������������������������������������������������� 86
Comparing Two Referenced Values��������������������������������������������������������������������������������������� 86
Quantities������������������������������������������������������������������������������������������������������������������������������������ 87
Parsing a String as Quantity�������������������������������������������������������������������������������������������������� 87
Using an inf.Dec as a Quantity����������������������������������������������������������������������������������������������� 88
Using a Scaled Integer as a Quantity������������������������������������������������������������������������������������� 89
Operations on Quantities������������������������������������������������������������������������������������������������������� 90
IntOrString����������������������������������������������������������������������������������������������������������������������������������� 90
Time�������������������������������������������������������������������������������������������������������������������������������������������� 92
Factory Methods�������������������������������������������������������������������������������������������������������������������� 92
Operations on Time���������������������������������������������������������������������������������������������������������������� 92
Conclusion���������������������������������������������������������������������������������������������������������������������������������� 93

Chapter 5: The API Machinery�������������������������������������������������������������������������������� 95


The Schema Package����������������������������������������������������������������������������������������������������������������� 96
Scheme��������������������������������������������������������������������������������������������������������������������������������������� 97
Initialization��������������������������������������������������������������������������������������������������������������������������� 98
Mapping������������������������������������������������������������������������������������������������������������������������������� 100

vii
Table of Contents

Conversion��������������������������������������������������������������������������������������������������������������������������� 101
Serialization������������������������������������������������������������������������������������������������������������������������� 103
RESTMapper����������������������������������������������������������������������������������������������������������������������������� 105
Kind to Resource����������������������������������������������������������������������������������������������������������������� 106
Resource to Kind����������������������������������������������������������������������������������������������������������������� 107
Finding Resources��������������������������������������������������������������������������������������������������������������� 107
The DefaultRESTMapper Implementation���������������������������������������������������������������������������� 107
Conclusion�������������������������������������������������������������������������������������������������������������������������������� 108

Chapter 6: The Client-go Library��������������������������������������������������������������������������� 109


Connecting to the Cluster��������������������������������������������������������������������������������������������������������� 110
In-cluster Configuration������������������������������������������������������������������������������������������������������� 110
Out-of-Cluster Configuration����������������������������������������������������������������������������������������������� 110
Getting a Clientset��������������������������������������������������������������������������������������������������������������������� 115
Using the Clientset�������������������������������������������������������������������������������������������������������������������� 116
Examining the Requests����������������������������������������������������������������������������������������������������������� 119
Creating a Resource������������������������������������������������������������������������������������������������������������������ 120
Getting Information About a Resource�������������������������������������������������������������������������������������� 122
Getting List of Resources���������������������������������������������������������������������������������������������������������� 123
Filtering the Result of a List������������������������������������������������������������������������������������������������������ 125
Setting LabelSelector Using the Labels Package���������������������������������������������������������������� 125
Setting Fieldselector Using the Fields Package������������������������������������������������������������������ 128
Deleting a Resource������������������������������������������������������������������������������������������������������������������ 130
Deleting a Collection of Resources������������������������������������������������������������������������������������������� 133
Updating a Resource����������������������������������������������������������������������������������������������������������������� 134
Using a Strategic Merge Patch to Update a Resource�������������������������������������������������������������� 135
Applying Resources Server-side with Patch����������������������������������������������������������������������������� 138
Server-side Apply Using Apply Configurations�������������������������������������������������������������������������� 140
Building an ApplyConfiguration from Scratch���������������������������������������������������������������������� 142
Building an ApplyConfiguration from an Existing Resource������������������������������������������������ 143

viii
Table of Contents

Watching Resources����������������������������������������������������������������������������������������������������������������� 145


Errors and Statuses������������������������������������������������������������������������������������������������������������������ 149
Definition of the metav1.Status Structure��������������������������������������������������������������������������� 149
Error Returned by Clientset Operations������������������������������������������������������������������������������� 153
RESTClient�������������������������������������������������������������������������������������������������������������������������������� 154
Building the Request����������������������������������������������������������������������������������������������������������� 154
Executing the Request��������������������������������������������������������������������������������������������������������� 161
Exploiting the Result������������������������������������������������������������������������������������������������������������ 161
Getting Result as a Table����������������������������������������������������������������������������������������������������������� 162
Discovery Client������������������������������������������������������������������������������������������������������������������������ 164
RESTMapper����������������������������������������������������������������������������������������������������������������������������� 165
PriorityRESTMapper������������������������������������������������������������������������������������������������������������ 165
DeferredDiscoveryRESTMapper������������������������������������������������������������������������������������������ 167
Conclusion�������������������������������������������������������������������������������������������������������������������������������� 167

Chapter 7: Testing Applications Using Client-go�������������������������������������������������� 169


Fake Clientset��������������������������������������������������������������������������������������������������������������������������� 170
Checking the Result of the Function������������������������������������������������������������������������������������ 171
Reacting to Actions�������������������������������������������������������������������������������������������������������������� 173
Checking the Actions����������������������������������������������������������������������������������������������������������� 177
Fake REST Client����������������������������������������������������������������������������������������������������������������������� 185
FakeDiscovery Client���������������������������������������������������������������������������������������������������������������� 188
Stubbing the ServerVersion������������������������������������������������������������������������������������������������� 189
Actions��������������������������������������������������������������������������������������������������������������������������������� 190
Mocking Resources������������������������������������������������������������������������������������������������������������� 190
Conclusion�������������������������������������������������������������������������������������������������������������������������������� 191

Chapter 8: Extending Kubernetes API with Custom Resources Definitions���������� 193


Performing Operations in Go����������������������������������������������������������������������������������������������������� 194
The CustomResourceDefinition in Detail����������������������������������������������������������������������������������� 195
Naming the Resource���������������������������������������������������������������������������������������������������������� 196
Definition of the Resource Versions������������������������������������������������������������������������������������� 197
Converting Between Versions���������������������������������������������������������������������������������������������� 198
ix
Table of Contents

Schema of the Resource����������������������������������������������������������������������������������������������������������� 199


Deploying a Custom Resource Definition���������������������������������������������������������������������������������� 201
Additional Printer Columns������������������������������������������������������������������������������������������������������� 204
Conclusion�������������������������������������������������������������������������������������������������������������������������������� 207

Chapter 9: Working with Custom Resources�������������������������������������������������������� 209


Generating a Clientset��������������������������������������������������������������������������������������������������������������� 209
Using deepcopy-gen������������������������������������������������������������������������������������������������������������ 211
Using client-gen������������������������������������������������������������������������������������������������������������������ 213
Using the Generated Clientset��������������������������������������������������������������������������������������������� 216
Using the Generated fake Clientset������������������������������������������������������������������������������������� 217
Using the Unstructured Package and Dynamic Client��������������������������������������������������������������� 217
The Unstructured Type��������������������������������������������������������������������������������������������������������� 217
The UnstructuredList Type��������������������������������������������������������������������������������������������������� 221
Converting Between Typed and Unstructured Objects�������������������������������������������������������� 223
The Dynamic Client�������������������������������������������������������������������������������������������������������������� 223
Conclusion�������������������������������������������������������������������������������������������������������������������������������� 229

Chapter 10: Writing Operators withthe Controller-­Runtime Library��������������������� 231


The Manager����������������������������������������������������������������������������������������������������������������������������� 232
The Controller��������������������������������������������������������������������������������������������������������������������������� 235
Creating a Controller����������������������������������������������������������������������������������������������������������� 236
Watching Resources������������������������������������������������������������������������������������������������������������ 237
A First Example������������������������������������������������������������������������������������������������������������������� 241
Using the Controller Builder������������������������������������������������������������������������������������������������ 244
A Second Example Using the ControllerBuilder������������������������������������������������������������������� 245
Injecting Manager Resources into the Reconciler��������������������������������������������������������������� 247
Using the Client������������������������������������������������������������������������������������������������������������������������� 250
Getting Information About a Resource��������������������������������������������������������������������������������� 250
Listing Resources���������������������������������������������������������������������������������������������������������������� 251
Creating a Resource������������������������������������������������������������������������������������������������������������ 254
Deleting a Resource������������������������������������������������������������������������������������������������������������ 254

x
Table of Contents

Deleting a Collection of Resources�������������������������������������������������������������������������������������� 255


Updating a Resource����������������������������������������������������������������������������������������������������������� 256
Patching a Resource������������������������������������������������������������������������������������������������������������ 256
Updating the Status of a Resource�������������������������������������������������������������������������������������� 259
Patching the Status of a Resource�������������������������������������������������������������������������������������� 260
Logging������������������������������������������������������������������������������������������������������������������������������������� 261
Verbosity������������������������������������������������������������������������������������������������������������������������������ 262
Predefined Values���������������������������������������������������������������������������������������������������������������� 262
Logger Name����������������������������������������������������������������������������������������������������������������������� 262
Getting the Logger from Context����������������������������������������������������������������������������������������� 263
Events��������������������������������������������������������������������������������������������������������������������������������������� 263
Conclusion�������������������������������������������������������������������������������������������������������������������������������� 265

Chapter 11: Writing the Reconcile Loop��������������������������������������������������������������� 267


Writing the Reconcile Function������������������������������������������������������������������������������������������������� 268
Checking Whether the Resource Exists������������������������������������������������������������������������������� 268
Implementing the Reconciled Resource������������������������������������������������������������������������������ 268
Simple Implementation Example����������������������������������������������������������������������������������������� 270
Conclusion�������������������������������������������������������������������������������������������������������������������������������� 275

Chapter 12: Testing the Reconcile Loop��������������������������������������������������������������� 277


The envtest Package����������������������������������������������������������������������������������������������������������������� 277
Installing envtest Binaries��������������������������������������������������������������������������������������������������� 277
Using envtest����������������������������������������������������������������������������������������������������������������������� 278
Defining a ginkgo Suite������������������������������������������������������������������������������������������������������������� 279
Writing the Tests����������������������������������������������������������������������������������������������������������������������� 283
Test 1����������������������������������������������������������������������������������������������������������������������������������� 284
Test 2����������������������������������������������������������������������������������������������������������������������������������� 285
Test 3����������������������������������������������������������������������������������������������������������������������������������� 285
Test 4����������������������������������������������������������������������������������������������������������������������������������� 285
Conclusion�������������������������������������������������������������������������������������������������������������������������������� 290

xi
Table of Contents

Chapter 13: Creating an Operator with Kubebuilder�������������������������������������������� 291


Installing Kubebuilder��������������������������������������������������������������������������������������������������������������� 291
Creating a Project��������������������������������������������������������������������������������������������������������������������� 291
Adding a Custom Resource to the Project�������������������������������������������������������������������������������� 293
Building and Deploying Manifests�������������������������������������������������������������������������������������������� 295
Running the Manager Locally��������������������������������������������������������������������������������������������������� 295
Personalizing the Custom Resource����������������������������������������������������������������������������������������� 296
Editing the Go Structures���������������������������������������������������������������������������������������������������� 297
Enabling the Status Subresource���������������������������������������������������������������������������������������� 297
Defining Printer Columns����������������������������������������������������������������������������������������������������� 297
Regenerating the Files�������������������������������������������������������������������������������������������������������� 298
Implementing the Reconcile Function�������������������������������������������������������������������������������������� 299
Adding RBAC Annotations��������������������������������������������������������������������������������������������������������� 299
Deploying the Operator on the Cluster�������������������������������������������������������������������������������������� 300
Creating a New Version of the Resource����������������������������������������������������������������������������������� 301
Defining a New Version������������������������������������������������������������������������������������������������������� 302
Implementing Hub and Convertible������������������������������������������������������������������������������������� 303
Setting Up the webhook������������������������������������������������������������������������������������������������������ 305
Updating kustomization Files���������������������������������������������������������������������������������������������� 306
Using Various Versions�������������������������������������������������������������������������������������������������������� 306
Conclusion�������������������������������������������������������������������������������������������������������������������������������� 308

Index��������������������������������������������������������������������������������������������������������������������� 309

xii
About the Author
Philippe Martin has been working with Kubernetes for
five years, first by creating an Operator to deploy video
CDNs into the cloud, later helping companies deploy their
applications into Kubernetes, then writing a Client to help
developers work in a Kubernetes environment. Philippe
has passed the CKAD, CKA, and CKS certifications. He has
extensive experience with distributed systems and open-
source software: he started his career 20 years ago creating
thin clients based on the Linux kernel and open-­source
components. He is currently working at Red Hat on the
Development Tools team.
Philippe has been active in the development of Kubernetes, especially its
documentation, and participates in the translation of the official documentation into
French, has edited two reference books about the Kubernetes API and kubectl, and is
responsible for the French translation of the Kubernetes Dashboard. He participated in
Google Season of Docs to create the new Kubernetes API Reference section of the official
documentation and is maintaining it.

xiii
About the Technical Reviewers
Bartosz Majsak writes code for fun and profit while proudly
wearing a red fedora (also known as the Red Hat). He has
been long-time open-source contributor and Java developer
turned into Golang aficionado. Bartosz is overly enthusiastic
about coffee, open source, and speaking at conferences,
not necessarily in that order. One thing that perhaps proves
he is not a total geek is his addiction to alpine skiing (and
running).

Prasanth is a Blockchain Certified Professional, Professional


Scrum Master, and Microsoft Certified Trainer who is
passionate about helping others learn how to use and gain
benefits from the latest technologies. He is a thought leader
and practitioner in Blockchain, Cloud, and Scrum. He also
handles the Agile Methodology, Cloud, and Blockchain
technology community initiatives within TransUnion
through coaching, mentoring, and grooming techniques.
Prasanth is an adjunct professor and a technical speaker.
He was selected as a speaker at the China International
Industry Big Data Expo 2018 by the Chinese government and also was invited to the
International Blockchain Council by the Government of Telangana and Goa. In addition,
he received accolades from the Chinese government for his presentation at China
International Industry Big Data Expo 2018. Prasanth has published his Patent, entitled
“Digital Educational Certificate Management System Using IPFS-Based Blockchain.”
To date, he has interacted extensively, reaching more than 50,000 students,
mostly within the technical domain. Prasanth is a working group member of the
CryptoCurrency Certification Consortium, the Scrum Alliance, the Scrum Organization,
and the International Institute of Business Analysis.

xv
Acknowledgments
I would like to thank the whole Anevia “CDN” team who started working with me on
Kubernetes back in 2018: David, Ansou, Hossam, Yassine, Étienne, Jason, and Michaël.
Special thanks to Damien Lucas for initiating this project and for having trusted us with
this challenge.
My discovery of Kubernetes has been much easier and pleasant thanks to the TGIK
channel and its numerous episodes, hosted by Joe Beda, Kris Nova, and many others.
Plus, thanks to all the Kubernetes community for such a great ecosystem!

xvii
Introduction
Back in 2017, I was working for a company building video streaming software. At the end
of that year, a small team, including me, got assigned a new job to work on deploying
the Video CDN developed by the company on Kubernetes. We decided to explore the
concept of Custom Resources and Operators to deploy this CDN.
The current Kubernetes release was 1.9, the concept of Custom Resource Definition
had just been released in 1.7, and the sample-controller repository was the only
documentation we knew of to help build an Operator. The Kubernetes ecosystem,
being especially lively, had tools appearing in the following months, specifically the
Kubebuilder SDK. Thus, our project was launched.
From that moment on, I spent numerous days exploring how to build Operators and
other programs interacting with the Kubernetes API. But the damage was done: I had
started to learn Kubernetes programming from specific to general, and it took me a long
time to fully understand the innards of the Kubernetes API.
I have written this book in the hope that it can teach new Kubernetes developers how
to program, from general to specific, with the Kubernetes API in Go.

Chapters at a Glance
The target reader for this book has some experience working with REST APIs, accessing
them either by HTTP or using clients for specific languages; and has some knowledge of
the Kubernetes platform, essentially as a user—for example, some experience deploying
such APIs or frontend applications with the help of YAML manifests.

• Chapter 1 of the book explores the Kubernetes API and how it


implements the principles of REST. It especially focuses on the
Group-Version-Resource organization and the Kind concept
proposed by the API.
• Chapter 2 continues by covering the operations proposed by the API
and the details of each operation, using the HTTP protocol.

xix
Introduction

• Chapters 3 to 5 describe the common and “low-level” Go libraries to


work with the Kubernetes API: the API and API Machinery Libraries.

• Chapters 6 and 7 cover the Client-go Library—the high-level library


to work with the Kubernetes API in Go—and how to unit test code
using this library.

At this point in the book, the reader should be comfortable with building Go
applications working with native resources of the Kubernetes API.

• Chapters 8 and 9 introduce the concept of Custom Resources and


how to work with them in Go.

• Chapters 10 to 12 cover the implementation of Kubernetes Operators


using the controller-runtime library.

• Chapter 13 explores the Kubebuilder SDK, a tool to help develop and


deploy Kubernetes Operators.

By the end of the book, the reader should be able to start building Kubernetes
operators in Go and have a very good understanding of what happens behind the scenes.

xx
CHAPTER 1

Kubernetes API
Introduction
Kubernetes is a platform to orchestrate containers operating in the declarative mode.
There are one-thousand-and-one ways to describe how the Kubernetes platform is
constructed. This book focuses on programming with the platform.
The entry point of the Kubernetes platform is the API. This chapter explores the
Kubernetes architecture by highlighting the central role of the Kubernetes API. It then
focuses on the HTTP REST nature of the Kubernetes API, and on the extensions added to
organize the many resources managed by it.
Finally, you will learn how to navigate the reference documentation effectively to be
able to extract the maximum quantity of useful information daily.

Kubernetes Platform at a Glance


On one side of the chain, the user declares the high-level resources to build applications
to deploy: Deployments, Ingresses, and so on.
In the middle, controllers are activated to transform these resources into low-level
resources (Pods), and the scheduler distributes these resources into nodes. On the other
side of the chain, the node agents deploy the low-level resources onto nodes.
The main elements of the Kubernetes platform (commonly called the control-plane)
are highlighted in Figure 1-1 and described in the following:

1. The API server – this is the central point on the control-plane; the
user and the various pieces of the control-plane contact this API to
create, get, delete, update, and watch resources.

2. The etcd database – this is only accessible by the API Server, is


used to persist the data relative to resources.

1
© Philippe Martin 2023
P. Martin, Kubernetes Programming with Go, https://doi.org/10.1007/978-1-4842-9026-2_1
Chapter 1 Kubernetes API Introduction

3. The Controller manager – this runs the controllers that transform


high-level resources declared by the user into low-level resources
to be deployed on nodes. The controllers are connected to the API
Server, watching for high-level resources and creating, deleting,
and updating low-level resources to satisfy the specifications
declared in high-level resources.

4. Scheduler – this distributes the low-level resources on the various


nodes. The Scheduler is connected to the API Server to watch for
unaffected resources and connect them to nodes.

5. Kubelet – this is an agent running on all nodes of the cluster,


and each agent manages the workloads affected to its node. The
kubelet is connected to the API Server to watch for Pods resources
affected to its node and to deploy the associated containers using
the local container runtime.

6. Kube proxy – this is an agent running on all nodes of the cluster,


and each agent manages the network configurations affected to
its node. The kube proxy is connected to the API Server to watch
for Service resources and to configure associated network rules on
its node.

2
Chapter 1 Kubernetes API Introduction

etcd
Kubectl
---

Control-plane
cre
at watch
de e set
up lete,
d
Controllers
wa ate
tch
API Server crea
te
te
dele te
a
upd
tch
wa

wa ate
tch
up
d
Kubelet
watch

Scheduler
no Kube-proxy
de
s

Figure 1-1. The architecture of Kubernetes

O
 penAPI Specification
The Kubernetes API is an HTTP REST API. The Kubernetes team provides a specification
for this API in the OpenAPI format, either in v2 format at https://github.com/
kubernetes/kubernetes/tree/master/api/openapi-spec or in Kubernetes v1.24,
in v3 format, at https://github.com/kubernetes/kubernetes/tree/master/api/
openapi-spec/v3.
These specifications also are accessible from the API Server at these paths:
/openapi/v2 and /openapi/v3.
An OpenAPI specification is made up of various parts and, among these, are a list of
paths and a list of definitions. The paths are the URLs you use to request this API, and
for each path, the specification gives the distinct operations such as get, delete, or post.
Then for each operation, the specification indicates what are the parameters and body
format for the request, and what are the possible response codes and associated body
format for the response.

3
Chapter 1 Kubernetes API Introduction

The parameters and bodies for requests and responses can be either simple types
or, more generally, structures containing data. The list of definitions includes data
structures that help build the parameters and bodies for the operations’ requests and
responses.
Figure 1-2 is a simplified view of a specification for a User API. This API can accept
two different paths: /user/{userId} and /user. The first path, /user/{userId}, can accept
two operations, get and delete, respectively, to receive information about a specific user,
given its user ID; and to delete information about a specific user, given its user ID. The
second path, /user, can accept a single operation, post, to add a new user, given its
information.
In this API, a definition of a structure User is given, describing the information for a
user: its ID, first name, and last name. This data structure is used in the response body of
the get operation on the first path, and in the request body of the post operation on the
second path.

4
Chapter 1 Kubernetes API Introduction

SDWKV
XVHU^XVHU,G`
JHW
SDUDPHWHUV
XVHU,GLQWHJHU
UHTXHVW%RG\ HPSW\
UHVSRQVHV

8VHU
GHOHWH
SDUDPHWHUV
XVHU,GLQWHJHU
UHTXHVW%RG\ HPSW\
UHVSRQVHV
 HPSW\
XVHU
SRVW
SDUDPHWHUV HPSW\
UHTXHVW%RG\8VHU
UHVSRQVHV

8VHU
GHILQLWLRQV
8VHU
,'LQWHJHU
)LUVW1DPHVWULQJ
/DVW1DPHVWULQJ

Figure 1-2. A simplified user API specification

V
 erbs and Kinds
The Kubernetes API adds two concepts to this specification: the Kubernetes API Verbs
and the Kubernetes Kinds.

5
Chapter 1 Kubernetes API Introduction

The Kubernetes API Verbs are mapped directly to the operations in the OpenAPI
specification. The defined verbs are get, create, update, patch, delete, list, watch, and
deletecollection. The correspondence with the HTTP verbs can be found in Table 1-1.

Table 1-1. Correspondence Between


Kubernetes API Verbs and HTTP Verbs
Kubernetes API Verb HTTP Verb

get GET
create POST
update PUT
patch PATCH
delete DELETE
list GET
watch GET
deletecollection DELETE

The Kubernetes Kinds are a subset of the definitions in the OpenAPI specification.
When requests are made to the Kubernetes API, data structures are exchanged through
the bodies of requests and responses. These structures share common fields, apiVersion
and kind, to help the participants of the request recognize these structures.
If you wanted to make your User API manage this Kind concept, the User structure
would contain two additional fields, apiVersion and kind—for example, with values v1
and User. To determine whether a definition in the Kubernetes OpenAPI specification
is a Kubernetes Kind, you can look at the x-kubernetes-group-version-kind field of the
definition. If this field is defined, the definition is a kind, and it gives you the values of the
apiVersion and kind fields.

Group-Version-Resource
The Kubernetes API is a REST API, and as a result of that it manages Resources, and the
paths to manage these resources follow the REST naming conventions—that is, by using
a plural name to identify a resource and by grouping these resources.

6
Chapter 1 Kubernetes API Introduction

Because the Kubernetes API manages hundreds of resources, they are grouped
together, and because the API evolves, the resources are versioned. For these reasons,
each resource belongs to a given Group and Version, and each resource is uniquely
identified by a Group-Version-Resource, commonly known as GVR.
To find the various resources in the Kubernetes API, you can browse the OpenAPI
specification to extract the distinct paths. Legacy resources (e.g., pods or nodes) will
have been introduced early in the Kubernetes API and all belong to the group core and
the version v1.
The paths to manage legacy resources cluster-wide follow the format /api/
v1/<plural_resource_name>—for example, /api/v1/nodes to manage nodes. Note
that the core group is not represented in the path. To manage resources in a given
namespace, the path format is /api/v1/namespaces/<namespace_name>/<plural_
resource_name>—for example, /api/v1/namespaces/default/pods to manage pods in
the default namespace.
Newer resources are accessible through paths following the format
/apis/<group>/<version>/<plural_resource_name> or /apis/<group>/<version>/
namespaces/<namespace_name>/<plural_resource_name>.
To summarize, the formats of the various paths to access resources are:

• /api/v1/<plural_name> – to access legacy non-namespaced


resources

Ex: /api/v1/nodes to access non-namespaced nodes resources

or

To access legacy namespaced resources cluster-wide

Ex: /api/v1/pods to access pods across all namespaces

• /api/v1/namespaces/<ns>/<plural_name> – to access legacy


namespaced resources in a specific namespace

Ex: /api/v1/namespaces/default/pods to access pods in the default


namespace

• /apis/<group>/<version>/<plural_name> – to access non-­


namespaced resources in specific group and version

Ex: /apis/storage.k8s.io/v1/storageclasses to access non-­


namespaced storageclasses (group storage.k8s.io, version v1)

7
Chapter 1 Kubernetes API Introduction

or

To access namespaced resources cluster-wide

Ex: /apis/apps/v1/deployments to access deployments across all


namespaces

• /apis/<group>/<version>/namespaces/<ns>/<plural_name> – to
access namespaced resources in a specific namespace

Ex: /apis/apps/v1/namespaces/default/deployments to access


deployments (group apps, version v1) in the default namespace

Sub-resources
Following the REST API convention, the resources can have sub-resources. A sub-­
resource is a resource that belongs to another and can be accessed by specifying its
name after the name of the resource, as follows:

• /api/v1/<plural>/<res-name>/<sub-resource>
Ex: /api/v1/nodes/node1/status

• /api/v1/namespaces/<ns>/<plural>/<res-name>/<sub-resource>
Ex: /api/v1/namespaces/ns1/pods/pod1/status

• /apis/<group>/<version>/<plural>/<res-name>/<sub-resource>
Ex: /apis/storage.k8s.io/v1/volumeattachments/volatt1/status

• /apis/<grp>/<v>/namespaces/<ns>/<plural>/<name>/<sub-res>
Ex: /apis/apps/v1/namespaces/ns1/deployments/dep1/status

Most Kubernetes resources have a status sub-resource. You can see, when writing
operators, that the operator needs to update the status sub-resource to be able to
indicate the state of this resource observed by the operator. The operations that can
be executed in the status sub-resource are get, patch, and update. The Pod has more
sub-resources, including attach, binding, eviction, exec, log, portforward, and proxy.
These sub-resources are useful for getting information about a specific running pod, or
executing some specific operation on a running pod, and so on.

8
Chapter 1 Kubernetes API Introduction

The resources that can Scale (i.e., deployments, replicasets, etc.) have a scale sub-­
resource. The operations that can be executed in the scale sub-resource are get, patch,
and update.

Official API Reference Documentation


The official reference documentation of the API can be found at https://kubernetes.
io/docs/reference/kubernetes-api/. The resources managed by the API are first
grouped together by category (i.e., workloads, storage, etc.), and for each category, you
can obtain a list of resource names with a short description (Figure 1-3).

Figure 1-3. The Kubernetes resources grouped by category

Note that these categories are not part of the Kubernetes API definition but are used
in this website to help inexperienced users find their way into the multitude of available
resources.

9
Chapter 1 Kubernetes API Introduction

To be precise, the name displayed is not the resource name in the REST sense, but
the associated principal kind, as shown in Figure 1-4. For example, when managing
Pods, the resource name used in the REST paths is pods (i.e., lowercase and plural), and
the definition used to exchange information about Pods during HTTP requests is named
Pod (i.e., uppercase and singular). Note that other kinds can be associated with the same
resource. In the example in this chapter, the PodList kind (used to exchange information
about Lists of Pods) also exists.

Figure 1-4. The resources for a specific category, with a short description

The Deployment Documentation


Let’s explore the reference page for the Deployment available at this address:
https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/
deployment-v1/. The title of the page, Deployment, is the principal kind associated with
the deployments resource shown in Figure 1-5.

10
Chapter 1 Kubernetes API Introduction

Figure 1-5. The Deployment documentation page

The apiVersion indicated in the header can help you write a YAML manifest for a
Deployment resource because you need to specify, for each resource in a Kubernetes
manifest, the apiVersion and kind.
In this case, you know the manifest for a deployment will start with the following:

apiVersion: apps/v1
kind: Deployment

The next header line indicates the import to use when writing Go code. In Chapter 3,
you will see how to use this import when describing resources in Go.

After the header, a list of structure definitions is described, also accessible from the
table of contents for the Deployment documentation page in Figure 1-6. The first one is
the principal kind of the resource, optionally followed by structure definitions that are
used in fields of the first kind.

11
Chapter 1 Kubernetes API Introduction

Figure 1-6. Table of contents for the Deployment documentation page

For example, the Deployment kind contains a spec field, of type DeploymentSpec,
which is described later. Note that DeploymentSpec is not a structure directly
exchanged during HTTP requests, and for that, it is not a kind and does not contain kind
or apiVersion fields.
Following the principal kind, and its associated definitions, other kinds associated
with the resource are displayed. In this case, the DeploymentList kind.

Operations Documentation
The next subject in the API Documentation for a resource is the list of possible
operations on this resource or its sub-resources, also accessible from the table of
contents page (see Figure 1-6). By examining the details for the create operation to
Create a Deployment, as shown in Figure 1-7, you can see the HTTP Request verb and
path to use, the parameters to pass during the request, and the possible responses. The
HTTP verb to use for the request is POST and the path is ­/apis/apps/v1/namespaces/
{namespace}/deployments.

12
Chapter 1 Kubernetes API Introduction

Figure 1-7. Details for a “create” Deployment operation

The {namespace} part of the path indicates a path parameter, which is to be


replaced by the name of the namespace on which you want to create the deployment.
You can specify the query parameters: dryRun, fieldManager, fieldValidation, and
pretty. These parameters will follow the path with the format path?dryRun=All.
The body of the request must be a Deployment kind. When using kubectl, you are
writing Kubernetes Manifests that contain this body. In Chapter 3, you will see how to
build the body in Go. The possible HTTP codes for the responses are: 200, 201, 202, and
401; and for the 2xx codes, the response body will contain a Deployment kind.

13
Chapter 1 Kubernetes API Introduction

The Pod Documentation


Some structures contain many fields. For them, the Kubernetes API documentation
categorizes the fields. An example is the documentation of the Pod resource.
The documentation page for the Pod resource first contains the description for the
principal kind, Pod, followed by the description of the PodSpec structure. The PodSpec
structure contains about 40 fields. To help you understand the relationships between
these fields and to simplify their exploration, they are arranged into categories. The
PodSpec fields’ categories are the following: Containers, Volumes, Scheduling, Lifecycle,
and so on.
Additionally, for fields containing nested fields, descriptions of them are generally
displayed inline to avoid a back and forth between structure descriptions. For complex
structures, however, the description is reported subsequently on the page, and a link is
present next to the field name to be able to access it easily.
This is always the case for the Spec and Status structures because they are very
commonly found in almost all the resources. In addition, this is the case for some
structures used in the Pod kind—for example, Container, EphemeralContainer,
LifecycleHandler, NodeAffinity, and so on.
Some structures used in several resources are placed in the Common Definitions
section, and a link is present next to the field name to access it easily. In Figure 1-8, you
can see the Containers category inside the description of the PodSpec structure.

14
Chapter 1 Kubernetes API Introduction

Figure 1-8. Extract of the PodSpec structure documentation

You also can see that the fields, containers and initContainers, are of the same
type as Container, which is described later on the page and is accessible with a link.
The imagePullSecrets field is of type LocalObjectReference, which is described in the
Common Definitions section and also is accessible through a link.

One-Page Version of the Documentation


Another version of the API Reference documentation exists and is presented on a single
page. This version covers all the versions of the resources served by a Kubernretes
version (not just the latest one). This version (if you want, change the last part of the path
to navigate to another Kubernetes version) can be found at the following URL:
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/

15
Chapter 1 Kubernetes API Introduction

Conclusion
In this chapter, you have been able to discover the architecture of the Kubernetes
platform, and that the API Server plays a central role. The Kubernetes API is an HTTP
REST API, and the resources are categorized into various versioned groups.
Kinds are specific structures used to exchange data between the API server and the
clients. You can browse, using the official Kubernetes website, the API specifications
in a human-readable form to discover the structure of the various resources and
kinds, the different operations available for each resource and sub-resource, and their
associated verbs.

16
CHAPTER 2

Kubernetes API Operations


The previous chapter described that the Kubernetes API follows REST principles and
enables users to manipulate resources.
In this chapter, you will learn how to perform various operations by making HTTP
requests directly. During your daily work, you probably will not have to interact directly
with the HTTP layer, but it is important to understand how the API works at this level so
that you can understand how to use more easily it with a higher-level library.

Examining Requests
Before starting to write your own HTTP requests, you can examine with kubectl which
requests are used when executing kubectl commands. This can be achieved by using
the verbose flag, -v, with a value greater than or equal to 6. Table 2-1 shows which
information is displayed at each level.
For example, if you want to know the URL that is called when getting pods for all
namespaces, you can use the following command:

$ kubectl get pods --all-namespaces -v6


loader.go:372] Config loaded from file:  /home/user/.kube/config
round_trippers.go:553] GET https://192.168.1.194:6443/api/v1/pods?limit=500
200 OK in 745 milliseconds

17
© Philippe Martin 2023
P. Martin, Kubernetes Programming with Go, https://doi.org/10.1007/978-1-4842-9026-2_2
Chapter 2 Kubernetes API Operations

In the output of the command, you can see that the path used is /api/v1/pods. Or,
when getting pods in a specific namespace, you can see that the path used is /api/v1/
namespaces/default/pods:

$ kubectl get pods --namespace default -v6


loader.go:372] Config loaded from file:  /home/user/.kube/config
round_trippers.go:553] GET https://192.168.1.194:6443/api/v1/namespaces/
default/pods?limit=500 200 OK in 138 milliseconds

Table 2-1. Verbosity Levels


Level Method Request Events Request Response Response Curl Body
and URL timing timing headers status headers cmd length

-v 6 yes yes – – – – – 0
-v 7 yes – – yes yes – – 0
-v 8 yes – – yes yes yes - ≤ 1024
-v 9 yes yes yes – – yes yes ≤
10240
-v 10 yes yes yes – – yes yes ∞

Making Requests
This section examines all the possible operations you can do with Kubernetes resources.

Using kubectl as a Proxy


You must be authenticated to make requests to the Kubernetes API of a cluster, unless
your cluster accepts unauthentified requests, which is unlikely.
A way to run authenticated HTTP requests is to use kubectl as a proxy to make it deal
with the authentication. For this, the kubectl proxy command can be used:

$ kubectl proxy
Starting to serve on 127.0.0.1:8001

18
Chapter 2 Kubernetes API Operations

On a new terminal, you can now run your HTTP requests without any
authentication. Next, a HOST variable to access the proxy is defined:

$ HOST=http://127.0.0.1:8001

Creating a Resource
You can create a new resource by first creating a Kubernetes manifest describing this
resource—for example, to create a Pod, you can write:

$ cat > pod.yaml <<EOF


apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
EOF

You then need to pass the resource description into the body of a POST request (note
that the -X POST flag can be omitted because the --data-binary flag is being used). For
example, to create a pod resource use:

$ curl $HOST/api/v1/namespaces/project1/pods
    -H "Content-Type: application/yaml"
    --data-binary @pod.yaml

This is equivalent to running the kubectl command:

$ kubectl create --namespace project1 -f pod.yaml -o json

Note that the namespace is not indicated in the pod.yaml file. If you add it, you must
specify the same namespace in the YAML file and in the path, or you will get an error—
that is, the namespace of the provided object does not match the namespace sent on the
request.

19
Chapter 2 Kubernetes API Operations

Getting Information About a Resource


You can obtain information about a specific resource using a GET request and passing its
name as a parameter (and its namespace if it is a namespaced resource) in the path. In
this example, you will request the information for the pod named nginx in the project1
namespace:

$ curl -X GET
    $HOST/api/v1/namespaces/project1/pods/nginx

This will return information about the resource in the JSON format, using the kind
associated with this resource as a structure; in this example, it is a Pod kind. This is
equivalent to running the kubectl command:

$ kubectl get pods --namespace project1 nginx -o json

Getting the List of Resources


For namespaced resources, you can get the list of resources either cluster-wide or in a
specific namespace. For non-namespaced resources, you can get the list of resources. In
any case, you will use a GET request.

Cluster-wide
To get the list of resources cluster-wide, for namespaced or non-namespaced resources;
for example, for the pod resource, use the following:

$ curl $HOST/api/v1/pods

This will return information about the list of pods in all namespaces, using a PodList
kind. This is equivalent to running the kubectl command:

$ kubectl get pods --all-namespaces -o json

In a Specific namespace


To get the list of resources in a specific namespace, you need to indicate the namespace
in the path; for example, for the pod resource, use this:

$ curl $HOST/api/v1/namespaces/project1/pods

20
Chapter 2 Kubernetes API Operations

This will return information about the list of pods in the project1 namespace, using a
PodList kind. This is equivalent to running the kubectl command:

$ kubectl get pods --namespace project1 -o json

Filtering the Result of a List


When running a list request, you get as a result the complete list of resources of this kind,
in the specified namespace or cluster-wide, depending on your request.
You may want to filter the result. The most common way to filter resources in
Kubernetes is to use labels. For this, resources need to have defined labels; then, during
a list request, you can define some label selectors. It also is possible to filter resources
based on a limited set of fields by using field selectors.

Using Label Selectors


All Kubernetes resources can define labels. For example, when creating pods, you can
define some labels with kubectl:

$ kubectl run nginx1 --image nginx --labels mylabel=foo


$ kubectl run nginx2 --image nginx --labels mylabel=bar

This results in pods with labels defined in the metadata part of the resource:

$ kubectl get pods nginx1 -o yaml


apiVersion: v1
kind: Pod
metadata:
  labels:
    mylabel: foo
  name: nginx1
[...]

$ kubectl get pods nginx2 -o yaml


apiVersion: v1
kind: Pod
metadata:
  labels:

21
Chapter 2 Kubernetes API Operations

    mylabel: bar
  name: nginx2
[...]

Now, when running a list request, you can define some label selectors to filter these
resources by using the labelSelector query parameter, which can contain a comma-­
separated list of selectors.

• Select all the resources defining a specific label, no matter its value;
for example, the mylabel label:

$ curl $HOST/api/v1/namespaces/default/pods?
labelSelector=mylabel

• Select all resources not defining a specific label; for example, the
mylabel label:

$ curl $HOST/api/v1/namespaces/default/pods?
labelSelector=\!mylabel

Note the exclamation point (!) before the label name—the backslash character (\)
is being used because the exclamation point is a special character for the shell.

• Select all resources defining a label with a specific value; for example,
mylabel having the value foo:

$ curl $HOST/api/v1/namespaces/default/pods?
labelSelector=mylabel==foo

or

$ curl $HOST/api/v1/namespaces/default/pods?
labelSelector=mylabel=foo

• Select all resources defining a label with a value different from a


specific one; for example, the label mylabel having a value different
from foo:

22
Chapter 2 Kubernetes API Operations

$ curl $HOST/api/v1/namespaces/default/pods?
labelSelector=mylabel\!=foo

Note the exclamation point (!) before the equal sign (=)—the backslash character
(\) is being used because the exclamation point is a special character for the shell.

• Select all resources defining a label with a value in a set of values; for
example, the label mylabel having one of the values foo or baz:

$ curl $HOST/api/v1/namespaces/default/pods?
labelSelector=mylabel+in+(foo,baz)

Note the plus characters (+) that encodes spaces in the URL. The original selector
being: mylabel in (foo,baz).

• Select all resources defining a label with a value not in a set of


values; for example, the label mylabel having a value different from
foo or baz:

$ curl $HOST/api/v1/namespaces/default/pods?
labelSelector=mylabel+notin+(foo,baz)

Note the plus characters (+) that encodes spaces in the URL. The original selector
being: mylabel not in (foo,baz).

You can combine several selectors by separating them with a comma. This will act as
an AND operator. For example, to select all resources with a label mylabel defined and a
label otherlabel being equal to bar, you can use the following label selector:

$ curl $HOST/api/v1/namespaces/default/pods?
labelSelector=mylabel,otherlabel==bar

23
Chapter 2 Kubernetes API Operations

Using Field Selectors


You can filter resources using a limited set of fields. For all resources, you can filter on the
metadata.name field; and for all namespaced resources, you can filter on the metadata.
namespace field.
Here is the list of additional fields available for filtering, depending on resources, for
Kubernetes 1.23:
core.event:
involvedObject.apiVersion

involvedObject.fieldPath

involvedObject.kind

involvedObject.name

involvedObject.namespace

involvedObject.resourceVersion

involvedObject.uid

reason

reportingComponent

source

type

core.namespace:
status.phase

core.node:

spec.unschedulable

core.pod:

spec.nodeName

spec.restartPolicy

spec.schedulerName

spec.serviceAccountName

24
Chapter 2 Kubernetes API Operations

status.nominatedNodeName

status.phase

status.podIP

core.replicationcontroller:

status.replicas

core.secret:
type

apps.replicaset:

status.replicas

batch.job:

status.successful
certificates.certificatesigningrequest:

spec.signerName

Now, when running a list request, you can indicate some field selectors to filter
these resources by using the fieldSelector parameter, which can contain a comma-­
separated list of selectors.

• Select all resources for which a field has a specific value; for example,
the field status.phase having the value Running:

$ curl $HOST/api/v1/namespaces/default/pods?
fieldSelector=status.phase==Running

or

$ curl $HOST/api/v1/namespaces/default/pods?
fieldSelector=status.phase=Running

• Select all resources for which a field has a value different from a
specific one; for example, the field status.phase having a value
different from Running:

$ curl $HOST/api/v1/namespaces/default/pods?
    fieldSelector=status.phase\!=Running

25
Chapter 2 Kubernetes API Operations

Note the exclamation point (!) before the equal sign (=)—the backslash character
(\) is being used because the exclamation point is a special character for the shell.

You can combine several selectors by separating them with a comma. This will act
as an AND operator. For example, to select all pods with a phase being equal to Running
and a restart policy not being Always, you can use this field selector:

$ curl $HOST/api/v1/namespaces/default/pods?
    fieldSelector=status.phase==Running,
    spec.restartPolicy\!=Always

Deleting a Resource
To delete a resource, you need to specify its name (and namespace for namespaced
resources) in the path and use a DELETE request. For example, to delete a pod, use the
following:

$ curl -X DELETE
    $HOST/api/v1/namespaces/project1/pods/nginx

This will return the information about the deleted resource in the JSON format, using
the kind associated with the resource—in this case, a Pod kind.
This is equivalent to running the kubectl command (except that you cannot get
information about the deleted resource, only its name with the -o name flag):

$ kubectl delete pods --namespace project1 nginx

Deleting a Collection of Resources


It also is possible to delete a collection of a given resource in a specific namespace, using
a DELETE request; and, for namespaced resources, indicating the namespace in the path:

$ curl -X DELETE
    $HOST/api/v1/namespaces/project1/pods

26
Chapter 2 Kubernetes API Operations

This will return the information about the deleted resources in the JSON format,
using the List kind associated with the resource; in this example, the PodList kind.
This is equivalent to running the kubectl command (except that you cannot get
information about the deleted resources, only their names with the -o name flag):

$ kubectl delete pods --namespace project1 --all

Note that it is not possible to delete all resources of a specific kind from all
namespaces in a single request the way you could do it with the kubectl
command: kubectl delete pods --all-namespaces --all.

Updating a Resource
It is possible to replace the complete information about a specific resource by using a
PUT request and specifying the name (and namespace for namespaced resources) in the
path and the new resource information in the body of the request.
To illustrate, you can first define a new deployment, with the following command:

$ cat > deploy.yaml <<EOF


apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
EOF
27
Chapter 2 Kubernetes API Operations

Then, you can create this deployment in the cluster using the following:

$ curl
    $HOST/apis/apps/v1/namespaces/project1/deployments
    -H "Content-Type: application/yaml"
    --data-binary @deploy.yaml

Next, you can create an updated manifest for the deployment; for example, by
updating the image of the container with the following command (this will replace the
image name nginx with nginx:latest):

$ cat deploy.yaml |
    sed 's/image: nginx/image: nginx:latest/' >
    deploy2.yaml

Finally, you can use the following request to update the deployment into the cluster:

$ curl -X PUT
     $HOST/apis/apps/v1/namespaces/project1/deployments/nginx
     -H "Content-Type: application/yaml"
     --data-binary @deploy2.yaml

This is equivalent to running the kubectl command:

$ kubectl replace --namespace project1


    -f deploy2.yaml -o json

Managing Conflicts When Updating a Resource


When updating a resource with the previous technique, if another participant makes a
modification on the resource between the time you create it and the time you update it,
then the modifications made by the other participant will be lost when you update the
resource.
To avoid this risk of conflict, you can first read the resource information (using a GET
request) to find the value of the resourceVersion field in the metadata of the resource,
then indicate this resourceVersion in the specifications of the resource you want
to update.
By sending the PUT request with this resourceVersion, the API server will compare
the resourceVersion values of the received resource and the current one. If the values

28
Other documents randomly have
different content
"Rakkaat juhlatoverit! Vaimoni, jolla ei suotta ole nimenä Eva, on
sanonut minulle: 'Jos aiotte viettää perustajaisjuhlaa Flackelholmilla,
pitää teidän kutsua naiset mukaan, juhla ilman naisia on kuin kukka
ilman tuoksua.' Niinpä olemmekin kutsuneet naiset mukaan,
emmekä kadu sitä. Olemme taaskin kerran saaneet tuta, että mies ja
nainen vasta yhdessä muodostavat kokonaisen ihmisen, ja säälimme
muutamia vanhimpia ystäviämme, että he ovat jääneet puolinaisiksi,
ja muutamia nuorista ystävistämme, että he vielä ovat puolinaisia."
— Peter Nahwer unohti säikähdyksissään imaista piippuansa. —
"Mutta keskessämme on kaksi, kaksi puoliskoa, jotka sopivat yhteen,
ja jotka siis lähimmiten yhtyvätkin, eläkööt Andrees ja hänen
morsiamensa, sulo Ingeborg, eläkööt!"

Kirkkaina ja heleinä kajahtivat naisten äänet.

Myöhemmin — kello oli noin neljä — siirrettiin muutamain naisten


pyynnöstä pöydät ja penkit välikölle ja ruvettiin tanssimaan. Se oli
jykevää tanssia, sillä miehillä oli pitkävartiset raskaat ojasaappaansa
yllään ja tukevista askelista jymähteli savipermanto. Peter Nahwer ja
lauluniekka Pellwormer, jolle olut hieman oli noussut päähän,
lauloivat vanhoja tanssisäveliä. Kun Heim tuli sisään kehoittamaan
lähtöön, seisoi Antje Witt säikähtyneen näköisenä hanhiensa edessä,
jotka olivat eräässä välikön nurkassa, heikon suojuksen takana ja
levitti hameenhelmojaan niitä suojellakseen, ja Pellwormer pyyhki
par'aikaa palasta kuivaa savea kaulukseltaan, jonne sitä oli lentänyt
jonkun saappaan korosta.

Nousuveden lasketessa lähtivät nuo viidet vankkurit paluumatkalle


ja saapuivat onnellisesti, ennen iltahämärän tuloa perille
mannermaalle.

*****
Pari viikkoa myöhemmin eräänä rauhaisana kesäkuun päivänä —
Frans Strandiger oli vielä Hampurissa — vietettiin häitä
Strandigerkartanossa. Sokea istui nojatuolissaan ihan niiden kahden
vieressä, jotka seisoivat alttarin edessä. Kumartuneena, pää
taipuneena eteenpäin, rauhallinen ilme kapeilla kasvoillaan kuunteli
hän nuoren papin korutonta puhetta. Perästäpäin kun vieraat olivat
jättäneet huoneen, lepäsi Ingeborg polvillaan hänen tuolinsa edessä
ja kätki vaalean päänsä vanhan rouvan syliin.

Pöydän ääressä syntyi vilkas, vaikka hillitty keskustelu. Haller


puheli rouva Strandigerin kanssa menneisyydestä, vapisevin käsin
etsi rouva hänen kätensä ja piti siitä: hän oli nähnyt ja kokenut
kaiken hänen kanssaan. Andrees nousi ylös ja kiitti lyhyesti kaikesta
ystävyydestä ja uskollisuudesta, joka oli tullut hänen osakseen
kotiseudulla. Heimilla oli aikomus puhua joku sana kolmesta
toveruksesta, mutta piti asiaa sentään liika arkaluontoisena ja alkoi
kiusata ja härnäillä Anna Halleria, joka istui pastorin rinnalla, ja meni
tietysti liika pitkälle. Syntyi silmäniskuja ja kuiskuttelua ympäri
pöytää: lopuksi loi Anna Haller kyyneleisen katseen Heimiin ja pakeni
äiti Strandigerin kammariin, josta pastori nouti hänet takaisin, kun
Ingeborg ensin oli käynyt lohduttamassa häntä.

Iltapäiväpostissa tuli, paitsi useita onnentoivotuskirjeitä, myöskin


kirje Frans Strandigeriltä, jossa hän ilmoitti, että hän jalansäryn
vuoksi oli pakotettu sanomaan irti vuokrasopimuksensa syksyksi.
Edelleen kertoi hän, että hän aikoi luovuttaa enonsa koko
omaisuuden. joka muuten teki enää ainoastaan kolmekymmentä
tuhatta markkaa, sisarelleen yksin. Kun Andrees oli antanut tämän
kirjeen rouvalleen, oli vielä edessään eräs virallinen kirjelmä,
varustettu yleisen syyttäjän virkasinetillä. Andrees Strandiger
kutsuttiin oikeuden eteen todistamaan huvijahti "Felixin" haaksirikon
johdosta. Oli nimittäin ilmennyt perusteltuja epäluuloja siitä, että
Hobookenin kanssapurjehtija, Frans Strandiger, oli tehnyt itsensä
syypääksi huolimattomuuteen.

Heim tuli, kun Andrees viittasi hänet luokseen, ja heitti miettivän


silmäyksen kirjelmään: "Hän on ollut liika ylpeä, puhuakseen itsensä
vapaaksi", sanoi hän. "Hän olisi voinut tehdä sen helposti, mutta
valehteleminen ei kuulu tapoihinsa."

He päättivät toistaiseksi vaieta asiasta. "Kirjoitan hänelle", sanoi


Andrees, "ja pyydän häntä ilmoittamaan, miten tämän syytteen
kanssa oikein on, ja mitä muita suunnitelmia hänellä on."

Iltapäivällä kello kolmen tienoissa jättivät Andrees ja Ingeborg


hyvästit äidilleen. Andrees voi nyt sanoa hänelle, että he molemmat
palaisivat hänen luokseen syksyksi, mahdollisesti jo aiemminkin.

Kun tänä iltana, onnellisesti suoritetun ylimenon jälkeen,


vastavihityt seisoivat rinnakkain vallilla ja iaskeuva aurinko laski
pitkiä kultaisia siltoja meren yli heidän luokseen, silloin tuntui heistä,
kuin seisoisivat he kahden Jumalan avoimien silmien edessä.
Ingeborgin suu sulkeutui, ja hänen silmänsä muuttuivat hiljaisiksi, ja
he ajattelivat menneisyyttä.

"Sinä olet muuttunut ihan toiseksi ihmiseksi, Andrees." sanoi


Ingeborg ja laski päänsä hänen olkapäätään vastaan.

"Olen saanut kokea paljon surullista."

Hetken perästä lisäsi hän: "Se on tehnyt minusta toisen ihmisen.

"Olet rauhallisempi ja samalla iloisempi."


"Niin… Minulla oli aiemmin omituinen tyytymätön halu nauttia
elämästä, kuten sanotaan. Kolkkoa nautintoa tuo! Nyt minulla on
rohkeutta tehdä ja luoda jotain: ja se on toista se. Ingeborg."

Ingeborg nojausi lujemmin häntä vastaan. "Tule", sanoi hän


tuokion kuluttua, "tulee viileätä."

He menivät alas viettävää vallitietä. Antje Witt tuli heitä vastaan


katsomaan lampaita, jotka olivat laitumella viheriällä kentällä.

Kun he molemmat tulivat väliköltä ensimmäiseen huoneeseen,


joka oli sisustettu yksinkertaisesti ja kodikkaasti — ovi toiseen
huoneeseen oli auki — heittäysi Ingeborg tulisen rakkautensa
valtaamana hänen rintaansa vastaan.

*****

Syksyllä palasi Frans Strandigerkartanoon takaisin — sittekun hän


jonkun kuukauden oli istunut vankilassa — luovuttamaan tilaa
Heimille. Taloa oli tänä kesänä vanhaan tapaan hoitanut vanha Hans
Stühen, joka monta vuotta oli rouva Strandigerin aikana ollut
talouden etunenässä.

Heim meni kohta kartanoon.

Frans Strandiger näytti jotakuinkin toipuneelta, ainoastaan kävi


hän kankeasti, ikäänkuin olisi rautaa jaloissaan.

"Hyvää päivää, Frans!" sanoi Heim. "Vaimoni lähettää terveiset."

"En ymmärrä", sanoi Frans nyrpeästi, "miten olet saanut noin


kelpo vaimon. Luulin varmasti, että sinä naimishommissasi tekisit
tuhmat kaupat."
"Kiitoksia!" sanoi Heim iloisesti. "Ilmoitan siitä rouvalleni. Noh.
sinähän näytät koko terveeltä. Olen iloinen, että olet noinkin
toipunut."

Frans naurahti katkerasti. "Toipunut? Kun käyn kaksikin tuntia


vaan tavallista kävelyä, ajettuvat jalkani."

"No… vähitellen paranee taas kaikki, ruumis ja sielu.

"Näyttää hiton epätietoiselta siinä suhteessa! En tiedä, mitä minä


ruumiilla, mitä sielulla. Teillehän tuo on kevyttä, on perintö maan
päällä ja perintö taivaissa."

"Hyvin sanottu!" tokaisi Heim. "Tuo oli hyvin sanottu, poikaseni.


Juuri maanpäällä olevan perinnön vuoksi olen tässä nyt, taivaallinen
perintö on sinun omakohtainen asiasi. Andreeksen puolesta on
minulla toimena kysyä sinulla, mitä suunnitelmia sinulla nyt on."

"Suunnitelmin?"

"Niinhän!"

Silloin istahti Frans raskaasti alas, eikä voinut salata


masentumustaan ja alakuloisuuttaan, niin paljon kuin hän koettikin
karaista itseään. "Minulla ei ole mitään suunnitelmia."

"Sanohan minulle, tahdotko ehdottomasti pois täältä?"

"Voinko jäädä tänne? Pitääkö minun ruveta pehtooriksi? Sinulla vai


Andreeksellako?… Se on totta, en ole niin vahva kuin ennen. Kun
vesi on neljä tuntia käynyt miestä kurkkuun… mutta siihen en
sentään vielä pysty mukautumaan."
Heim ravisti päätään. "Olet kiihdyksissäsi", sanoi hän. "Mutta
kuulehan! Näetkös! Me kaikki kolme, me toverukset, olimme
vieraissa ja olimme unohtaneet kotiseutumme, mutta tiemme johti
meidät kaikki tänne takaisin. Kun nyt olimme täällä, tapahtui
Andreekselle ja minulle näin: me rupesimme pitämään
synnyinseudustamme: myrskyssä otti se sydämemme. Nyt olemme
muuttuneet työntekijöiksi sen hyväksi, minä kaivaudun sen vanhoihin
aikakirjoihin ja teen väkivaltaa sen kankaille. Andrees on jo vuoden
ajat toiminut Flackelholmilla ja saanut aikaan suurta. Nyt kysyn
sinulta, kolmannelta toveruksista: lähdetkö sinä taaskin kotiseudulta
vieraisiin?"

Silloin nousi Strandiger ylös ja lähti ikkunan ääreen ja katseli ulos.


Länsituuli humisi jalavien latvoissa.

"Jäisinhän tänne", virkkoi hän viimein. "Olen jättänyt tänne


jalanjälkiä, jotka ovat astutut syvälle ja kahdesti olen kamppaillut
meren kanssa."

Heim nousi ylös ja astui nopeasti hänen luokseen. "Andrees


käskee kysyä sinulta, suostutko asettumaan asumaan Flackelholmille
ja hoitamaan saarta hänen puolestaan?"

Frans ei kääntynyt päinkään ja vaikeni hetken: "Soma ajatus",


sanoi hän sitte jyrkästi. "Maanpakoon! Flackelholmille tuo vaarallinen
otus!"

"Noh, jaa", murahti Heim… "Tiet täällä vanhalla manterella ovat


hieman kapeita sinun käydäksesi ja ihmiset, jotka käyvät niillä,
vaativat hiukan suurempaa arkatuntoisuutta, kuin mitä sinä olet
taipuva osoittamaan. Sinulla pitäisi olla suuri avara maatila, mutta
semmoista ei sinulla ole. Tai pitäisi sinun siirtyä länsi-Afrikaan; mutta
sitä et voi jalkojesi vuoksi. Mitäpä jää siis enää muutakaan eteen?
Flackelholmille! Siellä ei ole teitä, eikä ihmisiä! Saat viettää siellä
elämää, jommoista itse haluat. Kun sopii sinulle, teurastat oinaan, ja
pidät iloa asuntotoveriesi kanssa, ja taaskin, kun sopii, nouset
vallille, ja tähystelet Strandigerkartanon jalavia kohden, ja taaskin,
kun sopii sinulle, tulet tervehtimään ystävääsi Heim Heiderieteriä."

"Sen olen kauniisti jättävä tekemättä."

"Minä sanoinkin: jos sopii sinulle."

Hän asteli tuokion edes- ja takaisin. "Hän ei saa yhtäpäätä


sekaantua toimiini", sanoi hän sitte työläästi. "En tahdo tehdä tiliä
joka lapionpistosta."

"Et tarvitsekaan… Hän on jättävä sinulle vapaat kädet. Saat


toistaiseksi kymmenenä vuotena suorittaa vissien suunnitelmien
mukaan mittaustöitä. Kun valvot niiden toimeenpanoa, saat saaren
tulot palkaksesi. Hevoset ja veneen jättää hän käytettäviksesi.
Pyydän sinua, tule iltapäivällä meille kahville ja lue välikirja, jonka
Andrees on laatinut. Tulet tyytymään toimeen, jonka hän antaa
sinulle."

"Nuo hiton välikirjat!"

"No… olen iloinen, ett'et ole ihan haluton tuumaan. Jos saan
sanoa sinulle totuuden: niin olet sinä iloinen, että olet saanut tämän
tarjouksen. Sinä ja Flackelholm, te kuulutte yhteen. Raju ja ankara
olet sinä, raju ja ankara on morsiosi! Olet vielä antava haudatakin
itsesi Flackelholmille!"

"Tai jonnekin sen matalikoille tai aaltoihin."


"Kuinka Jumala sallii! Sinä tulet siis?"

"Tulen kahville rouvasi luokse."

"Toivoisin", sanoi Heim, "ett'eivät kolme uskollista toverusta


ainoastaan tuottaisi kunniaa nimelleen, vaan että he myöskin taas
tulisivat todellisiksi ystäviksikin."

Kahdeksan päivää myöhemmin lähti Frans Strandiger Büsenista


matkalle
Flackelholmille. Blauortin kohdalla tulivat venheet toisiaan vastaan.
Vaihdettiin pari sanaa, mutta eivät saaneet toisiaan kuulemaan.
KYMMENES LUKU.

Kolme toverustamme ovat nyt tulleet siihen ikään, jolloin ihminen


lakkaa olemasta yksin maailmassa, ja jolloin hän pyrkii päästä
jonkillaiseenkin sopuun maailman kanssa. Ihminen asettuu siinä
ijässä aina jollakin tapaa eturintaan. Hänestä tulee kansalainen,
jäsen, kanssatyöntekijä; yksi yhdellä alalla, toinen toisella. Yksi
hankkii itselleen jäsenyyden jossakin arvossapidetyssä
keilanheittoklubissa, toinen rupeaa kanssatyöntekijäksi johonkin
suurempaa vakavampaan tehtävään.

Kolme toverusta ovat siinä ijässä, jolloin ratkaistaan, tuleeko


ihminen elämänsä loppupuolella saavuttamaan ja toimittamaan
jotakin kelvollista ja arvokasta. Mitä merkitsevät nuoruusvuosina
lahjat? Ne muodostuivat monolle höyhenpatjaksi, jolla hän
loppupuolen elämäänsä lepää pehmeästi ja veltosti. Mitä merkitsee
avioliitto? Moni on siinä muuttunut epäluuloiseksi ja kiusoittavaksi.
Mitä merkitsee tulinen nuorekas innostus? Se on useasti heti
ensimmäisessä vinhemmässä tuulessa palelluttanut nenänsä. Mitä
merkitsevät hyvät aikomukset? Kun tuli aika toteuttaa ne, olivat ne
unohdetut.

Ne vuodot, jotka ovat kolmenkymmenen seutuvilla, ne ratkaisevat.


On kolmesta toveruksestamme sanottava, että he herättävät hyviä
toiveita. He ovat kaikki kolme sanan hyvässä merkityksessä
nykyaikaisia ihmisiä; heissä ilmenee näiden kaksi esiintyvimpää
ominaisuutta: he tietävät, että he ovat jotakin, ja heissä elää
vakaumus, että heidän pitää auttaa, neuvoa ja tehdä työtä.

Andrees seisoo ylpeällä voimakkaalla tietoisuudella kristillisen


maailmankatsomuksen pohjalla. Hänellä on Herra, joka on voimakas
ja väkevä, ja hän on palveluksessa, joka on kaunis. Tuon
muinaisajan pakanan tosikristillinen sana: "En ole olemassa
vihatakseni, vaan rakastaakseni", on kuin lausuttu hänen sisimmästä
sielustaan. Hän on tyyni mies, jonka ajatukset liikkuvat hitaasti,
mutta joka toimii terävästi ja varmasti. Ystävänsä perustauvat hänen
sanoihinsa, ei siksi, että ne olisivat ehdottomasti oikeat, vaan siksi,
että he tietävät, että ne ovat tunnollisen ajattelun tuloksia.

Kun tuli ratkaistakseen, miten heidän tulisi menetellä Maria


Landtin omaisuuden kanssa, jota ei hän eikä Ingeborg tahtoneet
käyttää omaksi hyväkseen, eivät he kumpikaan kauvan epäilleet.
Kukaan ei seuduillamme tunne paremmin kuin Andrees Strandiger,
missä on maatyömiesten puutteen juuri. He ovat, vakuutettuina siitä
että siinä toimivat vainajan mielen mukaisesti, perustaneet vainajan
rahoilla "Maria Landtin rahaston", Strandigerkartanon rajalle,
Stülperkoogia päin. tien varrelle, on näillä rahoilla perustettu pari
pientä palstatilaa, ja etelään metsästä, Heimin kankaan rajalle, jossa
maapohja on saviperäistä, toiset viisi, joiku samoin ovat kooltaan
pieniä, ja myyty ne nuoremmille kunnollisille työmiehille. Näiden
tilojen raha-asiat järjestettiin valtion hypoteekkipankin välityksellä;
lahjarahaston pääoman tarkoituksena on ainoastaan helpottaa tilalle
pääsemisiä, ja keventää korkotaakkaa senverran, että se tulee
siedettäväksi.
Andrees Strandiger on kaikella sillä ahkeruudella,' jota tämä
tehtävä vaatii ja kaikella tunnollisuudellaan antaunut tilansa hoitoon.
Kaikkien noiden palstatilojen avulla, joita hän muodosti kartanonsa
lähistölle, on hänelle ollut mahdollista hankkia itselleen valiojoukko
kelvollista työväkeä. Loput saa hän nummikylistä, nekin kelpoa
maataomistavaa väkeä.

Ajan tarve ja vaivanalaisuus, jota hän näkee ympärillään, ja


tyytymättömyys, joka on vallannut niin monet mielet, on saanut
hänen tulisella innolla ja kaikella tunnollisuudellaan ja
perinpohjaisuudellaan antaumaan kansantaloudellisiin tutkimuksiin.
Kuntalaisten luottamus on tehnyt hänestä kunnan esimiehen,
maakunnan luottamus on asettanut hänet maanviljelysseurojen
johtoon, kohta on hän istuva piiripäivillä, ja lopuksi myöskin
maakuntapäivillä. Näitä asioita käsittelee hän tunnollisuudella, joka
lähentelee turhantarkkuutta.

Luonnollisesti ei ole hänenkään taivaansa ihan pilvetön. Missä on


perhe, jolla ei olisi ristiänsä? Jos hän johtuu ajattelemaan
menneisyyttään, saa rouva Ingeborg ponnistaa kaikkensa,
saadakseen häntä rohkaistuksi taas. Kun hän kerran luki erään
suuren kansanmiehen teoksessa sen sanan, että ihminen tekee
viisaasti, jos hän nuoruudessaan omistaa jonkin asian omakseen,
jonka vielä täytyy taistella edistääkseen, silloin on hänellä
vanhuudessaan oleva ilo saada nähdä sen hänen apunsa kautta
voittaneen, silloin valtasi hänet alakuloisuus ja mielemnasennus
useaksi päiväksi; hän ajatteli turhaankuluneita nuoruusvuosiaan.

Frans Strandiger asuu jo vuosia sitte Flackelholmilla. Hän ei ole


ruumiillisesti terve. Tuo jättiläisvahva on nyt enää ainoastaan vahva,
ja valittaa usein, että kun hän viisituntiakin vanu astelee hiekassa ja
liejussa niin jalkansa rupeavat sattumaan ja ajettuvat. Hän on yhä
vielä itsevaltiailla taipumuksilla varustettu mies, eikä osaa tulla
ihmisiä persoonallisesti lähelle, ne ovat hänen työntekijöitään tai
miehiä, joille hän antaa neuvoa ja apua saadakseen niiltä samalla
mitalla takaisin. Hän on muuttunut kuitenkin kohtuullisemmaksi ja
oikeamielisemmäksi. Siitä saakka kun hän omassa ruumiissaan sai
kokea, että hänenkin, niin vahva kun olikin, olisi täytynyt sortua
ilman Jumalan ja ihmisten apua, on hän muuttunut lauhemmaksi.

Hän on oikea uskollinen. Elämänsä on vaivalloista, ankaraa,


yksinäistä. Se ei ole vaaroitta, ja voi kylläkin tapahtua, että hän
löytää loppunsa joskus matalikolla tai aalloissa. Häntä pidetään
kaiken sen hyvänä tuntijana, mikä koskee Pohjanmeren rannikkoa, ja
hänellä on monellaisia suunnitelmia. Rantatokeitten rakentaminen,
merisammalen koonti, ulkomerikalastus ovat asioita, joissa
ajatuksensa yhtäpäätä liikkuvat. Mutta kun kerran joku esitti, että
pitäisi Flackelholmista muodostaa kylpypaikka, naurahti hän lyhyesti,
kuten naurahdetaan suurelle tuhmuudelle.

Politiikasta — sanan ahtaammassa merkityksessä — hän ei välitä


hituistakaan; hän välittää ainoastaan omista asioistaan. Mutta hän
on kaikissa ranta-asioissa valtion luottamusmiehenä, ja näyttää siltä,
kuin saisi hän joskus sen kunniamerkin, jota Heim kerran toivoi
itselleen. Hän seuraa harrastuksella siirtomaakysymyksiä: se onkin
ainoa tiehyke, jolla hän on yhteydessä muun maailman kanssa. Hän
tuntee Kielissä useita laivastoupseereita, jotka ovat tehneet
mittauksiaan Flackelholmilla, ja jos olisi hänellä lapsia, poikia samaa
maata kuin hän itsekin, niin odottaisi hän että niistä tulisi
uutisasukkaita Lounaisafrikaan tai kauppamiehiä Kiautschouhun.
Luonnollisesti on hänelläkin vikansa ja virheensä. Missä olisi
ihminen, jolla ei niitä olisi? Hänen puutteensa on, että hänen, Frans
Strandigerin, syntyperäisen herran ja käskijän, pitää elinijäkseen
jäädä toisen omaisuuden hoitajaksi, toisen määräysten
toimeenpanijaksi.

Heim Heiderieteristä on tullut kirkonvanhin. Se merkitsee, että hän


on päätä pitempi kaikkia Heiderietereitä. Milloinkaan ennen ei ole
sitä tointa uskottu millekään Heiderieterille. Olivat kyllä sanoneet
ett'eivät voineet käyttää häntä kirkon rakennusmestariksi. Mutta sitä
ei oltu tarkoitettu moitteeksi, päinvastoin; sillä he lisäsivät: "Siihen ei
sinulta nimittäin riitä aikaa, Heim. Kirkon rakennusmestariksi pitää
valita mies, joka alkaa olla koroillaan eläjä, ja joka haastelutaidollaan
osaa estää työmiehiä työskentelemästä itseään turmiolle
kirkontyössä."

Entiskesänä, noin keskikesästä, sattui Heimille suuri ilo.

Hän seisoi noin kello lähemmä neljää paidanhihoissaan ovella, ja


oli katselevinaan varpusia, jotka leikkivät koulupihalla, sill'aikaa kun
lapsilla oli elonkorjuuloma. Itse asiassa odotti hän sentään
kirjeenkantajaa, joka juuri oli kadonnut koulutaloon. Ei oiekkaan
mikään vähäpätöinen asia, kun tuommoinen toivorikas, epäilysten
ahdistama ja niin täydellisesti itsetietoisuutta vailla oleva kirjailija on
lähettänyt ensimmäisen suuremman käsikirjoituksensa matkalle.

Koulunovi aukeni. Heim tähystelee varpusia kohden vaan ja näkee


kuitenkin, että kirjeenkantaja lähenee hänen oveaan, mutta ei näe,
että Haller seisoo koulunovella.

Kirje!
Kirje kustannusliikkeeltä Berlinissä! Ei siis käsikirjoitusta!

Kuori lentää säpäleiksi. "Mitä seisoo siinä? Mitä? 'Viisitoistasataa


markkaa? Jos suostutte?' Eva! Eva! Tule tänne! Eva Heiderieter,
missä olet?"

Hallernaapuri rientää pitkin ja, huolimalta tukevuudestaan,


kiirehtivin askelin tien poikitse, takkinsa helmat, jotka eivät oikein
tahdo ennättää tehdä seuraa, lentävät jälestä.

Väliköllä on Heim saanut Evansa syliinsä. "Viisitoistasataa


markkaa! Sano nyt jotain! Jotakin nyt! Mitä teemme nyt?
Rakennamme uuden talon vai? Poika saa uudet saappaat! Jürgen!
Valjasta eteen! Uuden hienon villahameen saat sinä!" Hän hellitti
hänestä, juoksi edestakaisin, ravisteli yhtämittaa päätänsä ja polki
jalallaan lattiaan. Silmänsä olivat paljasta loistoa.

Silloin ei malttanut enää mies ovessa itseään: "Poikaseni, Heim!"

"Naapuri, mitä sanotte?" Hän tarttui ukkoa molemmin käsin, ja


yht'äkkiä, kun hän näki noihin vanhoihin kasvoihin, puhkesi hän
sanomaan: "Olisi Frisius elänyt tämän!"

"Jos hän olisi elänyt tänään", sanoi Haller, "olisi hän kohottanut
etusormeaan, näinikään, kuten hänen oli tapansa", — hän kohotti
etusormeaan ilmaan — "ja olisi sanonut: 'Haller! Ette sittekään ole
oikeassa. Heiderieterit ovat terävää, mutta laiskaa väkeä. Ett'ei hän
nyt vaan tulisi laiskaksi!'"

Heim nauroi.

Eva juoksi kyökkiin. Siellä seisoi kaksi pientä Heiderieteriä


vasikkapurtilon edessä, ja vanhempi, nelivuotias koetti syöttää
lusikalla, jossa oli leseitä, pienempää veljeään ja tämä kahmaisi
kohden. Eva polvistui lasten viereen, pyyhkäsi kerran esiliinallaan
pienemmän suuta ja ajatteli: "Viisitoistasataa markkaa! Kuinka
tarpeen ne olivatkaan! Viisitoistasataa markkaa! Andrees saa
lainaamansa kaksisataa takaisin, uudet vankkurit voimme ostaa ja
raivauttaa kaksi hehtaaria uutta maata, voimme pitää molemmat
joutikkaat ja vuorata uudestaan länsiseinän, ja ostaa lapsille paitoja
ja äidille uuden puvun. Tuossa taisin mennä sentään jo liika pitkälle.
Äidin uusi puku saakoon jäädä! Kuinka hän on iloissaan! Hän iloitsee
kuin lapsi! Nytkös on itseuskalluksensa kasvava… nyt hän ei vaan
saa tulla ylpeäksi…" Hän istui vielä hetken kyyristyneenä lieden
ääressä, tulenvalo lankesi hänen tummille suortuvilleen, kätensä
olivat ristissä. "Huolista rikas on elämä, mutta siunauksen onnea on
siinä myöskin. Siinä suhteessa erehdyin hänessä, hän näytti niin
voimakkaalta silloin Heidelbergissä… mutta hän on pehmeä. Mutta
tahtonsa on hyvä ja rakkautensa vilpitön. Minä kiitän siitä koko
sydämelläni."

"Tiedätkö, äiti", sanoi pikkulapsi, "nyt minä tiedän jo laulun, jota


pääskyset laulavat. Ne istuvat tuvanovella ja laulavat. Kuulehan
vaan":

Näin pikku pääskyemon


Nyt laulu soi:
"Mun Heikkini, Heikki, mun Heikki,
Riens' aika, oi:
Pesässä näät
Jo keltapäät,
Nuo äänekkäät!
Ken elättää ne voi!"
Niin laulaa pieni Heikki
Nyt vuorostaan:
"Mun Liisuni, Liisu, mun Liisu,
Sua muistin vaan!
On lämmin sää,
Ja sääsket nää
Nepä elättää!
Et Herraan Iuotakkaan?"

Näin laulavat yhdessä sitten


Nuo pienoiset:
"Mun Liisuni, Heikki, mun Liisu,
Pois huolet net!
Ilo toistaiseksi,
Sen ihmiset keksi;
Me nyt iloitaan,
Suru tuonnempaan!
Nyt lentohon taas, kvi-tet!"

Silloin astui Heim kyökkiin, ja kun hän näki hänet siinä


kumartuneena ja hiljaisin kasvoin, tunsi hän nähtävästi, mitä hänen
sydämessään liikkui. Hän nosti hänet ylös ja sanoi: "Eva, sinun pitää
aina saada olla onnellinen."

"Minä olen onnellinen. Heim. Olen aina ollut onnellinen siitä


saakka kuin olen sinun vaimosi. Sinä pidät minusta, ja meillä on
leipää, ja meillä on rakkaat armaat lapsemme."

Sitte istuivat he vierekkäin lieden reunalla. Valkea leimuili


vieressään ja heidän kasvonsa loistivat ja he rakentelivat
suunnitelmia.
Tämä päivä toi mukanaan vielä toisenkin odottamattoman
tapauksen. Kun Heim oli hieman rauhoittunut ja Evan ollessa ulkona
laitumella lypsämässä lehmiä, aukaistiin ulko-ovi ja joku tulla laahusti
tohvelit jaloissaan välikön poikki. Heim meni mitään aavistamalta
lasiovelle ja oli hieman äkeissään siitä että häntä oli tultu
häiritsemään, hänelle kun juuri oli sattunut niin kauniita ajatuksia.
Silloin kun hän avaa oven, seisoo siellä koko pyyleydessään, jäykässä
kädessään valkea huolellisesti 'taiteilu nenäliina ja puettuna
tunnettuun päällyshuiviinsa, Thiel eukko.

"Thiel mummo! Mutta! Mummu Thiel toki!"

"Annahan minun istua nyt toki ensin", pakisi tämä. "Ei ole mitään
leikintekoa tuommoinen noin pitkä matka vanhalle vaimolle."

"Nahkatossuissa."

"Ne ovat ne suutari Ketelsin tekemät. Ja sanon sinulle, niitä ei olo


vielä kertaakaan tarvinnut puol'anturoida senjälkeen."

"Mutta miksi palaatte takaisin, äiti Thiel?"

"Miksikä?… Arvelet kai, ett'en olisi löytänyt takaisin, sinä kun


jaarittelit minulle, muistatko vielä, turvevasusta? Onko maa mikään
turvevasu? Miksi jaarittelit vanhalle ihmiselle tuommoista?"

"Niin, äiti Thiel, mutta miksi tulette takaisin nyt?"

"Miksikä? Luuletko sinä, että aion lahjoittaa niille rahat, jotka


tulevat minulle Henrikin tähden ja vanhuuden vakuutuksestani?"

"Eikö niitä ole lähetetty teille?"


"Onhan niitä lähetettykin! Mutta useasti e niitä tullut, ja kuu tuli.
sanoivat tytöt aina, että juuri silloin välttämättä tarvitsivat rahaa."

"Mutta kuulkaas, äiti Thiel, eikö sentään ollut parempi siellä


lastenne luona. Täällähän olette sentään ihan yksin ja turvatonna?"

Silloin laski vanha mummo tukevat kätensä kenoon polviansa


vastaan ja sanoi tuimasti: "Lapseni olivat iloissaan, Heim, ja
lastenlapseni myöskin. Australiassa iloitsivat oikein englanniksikin,
sillä ne eivät osanneet sanaakaan saksaa. Mutta kun olin hiukankin
istahtanut, niin kuului kohta: 'Äiti, tekisitköhän tämän? Äiti, voisit
hiukan auttaa minua tässä!' Monasti sanoivat he suoraan: 'Äiti,
otahan tuo poika', ja samassa oli minulla jo tuo säpyttelevä lapsi
sylissäni. Ja siihen. Heim, siihen en ole enää tottunut. Kun minulla
itselläni oli pieniä lapsia, silloin olin kyllä nopsa huolehtimaan niistä,
mutta nyt en enää viitsi tuommoista. Olen iloinen, että vielä kerran
olen saanut nähdä heidät, enempää en halunnutkaan."

Hän nousi raskaasti ylös — hän oli sentään tullut vanhemmaksi —


ja lähti välikölle. Ovella kääntyi hän vielä kerran taakseen ja sanoi:
— "Kunnan kirjurin luona olen jo käynyt rahojen vuoksi! Hän sanoi,
että kaikki suoritetaan viipymättä! Siten ihan sanoi hän, Heim,
'suoritetaan viipymättä!' Hän on kelpo mies hän, Heim."

Hiekkatiellä kääntyi hän vielä kerran taakseen: "Terveiset


rouvallesi!
Käyvätkö lehmät tänä vuonna Puroniityllä? Onko teillä hyvää maitoa?
No… olin ihan unohtaa, millä asialla olin! Sano Evalle, että hän joka
ilta panee minun varalleni puolen litraa maitoa."

Pellwormer, joka korjaili erästä epäkuntoon joutunutta seinäkelloa,


joka oli tuotu hänelle laitettavaksi, ei virkannut Silminkään, kun Thiel
eukko yht'äkkiä ilmestyi tuvan oveen. Eukko lyödä läiskäytti häntä
olalle.'"Älä nyt sano sanaakaan ensimmäisenä puolena tuntina! Sitte
luistaa se jälkeenpäin paremmin." Sitte alkoi hän kohennella
valkeata, joka oli melkein sammuksissa ja vanhaan tapaansa
varustaa kahvia.

On vaikeata sanoa mitään kirjailija Heiderieteristä. Olisi


kevytmielistä lausun hänestä varmaa arvostelua, koska hän vielä on
kehittymässä. Huomautettakoon tässä ainoastaan, että hänellä on
suunnitelmana esittää Schleswig-Holsteinin historian huippukohdat
romaaneissa, ja että ensimmäinen näistä romaaneista, jonka
tapahtuma-aika on kahdennellatoista vuosisadalla, on jo ilmestynyt.
Muuten voi jokainen, joka tarkkuudella on lukenut nämä lehdet,
joissa niin paljon on ollut puhetta Heim Heiderieteristä, muodostaa
itselleen kuvan hänestä.

Täten ovat siis kolmen toveruksemme asiat.

Ei ollut syntynyt mitään laakeriseppeleestä, ei ollut raha-


arkustakaan, eikä ritarimerkistä. Elämä on laskenut kullekin heistä
heidän taakkansa. Mutta he eivät nurise, eivätkä ole muuttuneet
epäluuloisiksi, kuten moni. He eivät seiso toimettomina ja anna
toisten ahertaa ja ahkeroida, kuten moni. He eivät ota kansalta
antamatta mitään takaisin, kuten moni tekee. Ne eivät morkkaa
hallitusta, kuten moni muu: vaan tekevät he työtä hallituksen ja
kansan kanssa.

Kolmen toveruksen keskinäiset välit jättivät useat vuodet vielä


paljon toivomisen varaa. Andrees ja Heim näkivät toveriaan
Fiackelholmilla harvoin. Strandigerkartanoon hän oi tullut,
Ingeborgin näki kerran tai pari, kun he sattumalta kohtasivat
toisensa kaupungissa.
Kuitenkin joutuivat he vähitellen lähemmäksi toisiaan. Siihen
vaikutti etenkin eräs matka, jonka aiheutti Heim. Hän kehoitti
kumpaakin toista matkustamaan kanssaan Kieliin, jossa hän aikoi
käydä katsomassa erästä käsikirjoitusta yliopiston kirjastossa. Kun
Andreeksella oli tehtäviä Hampurissa, niin päätettiin tehdä matka
Hampurin kautta, ja, jos vaan mahdollistu, saada nähdä
Friedrichsruhe'ssa vanha Bismarck. Andrees lähti sitä mieluummin
Kieliin, kun hän toivoi siellä saavansa kohdata muutamia valtiollisia
ystäviään. Rouvien piti seurata mukana. Frans suostui hetken
arveltuaan purjehtimaan ylös Elbeä ja yhtymään Hampurissa toisiin.

Koko matka sujui toivojen mukaan, vaikkakin Frans, varsinkin


Ingeborgin läsnäollessa pysyikin hyvin umpimielisenä. Hampurissa
kävivät he ihanimmassa ilmassa ja Fransin ohjaamina katselemassa
uusia mahtavia satamalaitoksia. Se oli ikäänkuin katsaus avaraan
maailmaan, jossa kansat ovat muuttuneet rauhaisiksi kauppiaiksi.
Friedrichsrnhe'ssa oli heillä onni saada ei ainoastaan nähdä
ruhtinasta, vaan vieläpä puhutellakin häntä. Kun hän nimittäin tuli
tietä, joka vie tuolla puolen aseman ylös metsään, miellyttivät häntä
arvatenkin nuo kolme voimakasta reipasta miestä, joiden rinnalla
seisoi kaksi komeata rouvaa. Vaunut pysähtivät, ja hän kysyi
ystävällisesti: "Mistä matka?" ja "Minne?" Lopuksi kysyi hän: "Vieläkö
nostoväessä?" Silloin sanoi Heim, kohottautuen suoremmaksi ja
painolla: "Niinkauan kuin elämme, armonne!" Silloin nyökäytti
vanhus päätään, loi heihin mahtavat silmänsä ja ajoi edelleen.

Kielissä kutsuttiin naiset erääseen tuttavaan perheeseen: miehet


menivät kukin omia teitään, ja on kuvaavaa, minne kukin suuntasi
askeleensa. Andrees meni erääseen suureen kansankokoukseen,
jossa työmiehiä kehoitettiin luopumaan hedelmättömästä
vastustuksesta hallitusta vastaan, ja, samoinkuin toverinsa
Englannissa, työskentelemään rohkeudella ja luottamuksella
isänmaan edistymisen eteen. Sittemmin, kun hän illan puhujain ja
muutamain muiden valtiollisten ystäväinsä kanssa vietti iltaa
yhdessä, pyysivät he häntä vähitellen totuttautumaan siihen
ajatukseen, että hän asettuisi valtiopäivämiesehdokkaaksi
kotipiirissään, jossa juuri oli edusmiessija avoimena. On
otaksuttavaa, että hän raskain sydämin on ryhtyvä tähän tehtävään,
mutta hän ei ole kieltäytyvä noudattamasta ystävänsä toivomusta,
eikä pettävä niin monen ymmärtävän miehen luottamusta.

Frans vietti iloisen illan muutamain tuttavain meriupseerien


kanssa, jotka riemulla ottivat vastaan Flackelholmin kuninkaan.
Istunnon lopputuloksena oli, että he kehoittivat häntä pikimmiten
menemään naimisiin, sillä koska hän itse oli estetty lähtemästä
siirtomaihin, olisi hänen velvollisuutensa huolehtia, että joskus edes
poikansa voisivat astua tallo tielle.

Heim taas istui erään professorin hupaisessa työhuoneessa, tämä,


joka oli etevä Schleswig-Holsteinin historian tuntija, oli jo alusta
alkaen vilkkaalla myötätunnolla tutustunut Heimin teoksiin.

Hyvällä mielialalla ja tuntien, että matka oli tuonut heitä


lähemmäksi toisiaan, palasivat nämä viisi kotiin.

*****

Muutamaa päivää myöhemmin, alussa syyskuuta, seisoi Frans


Strandiger, pyssy olallaan, ja muutamia ampumiaan suorsia
kädessään Flackelholmin korkeimmalla säikällä ja katsella pälyili
Büseniä kohden, jonka rakennukset selvästi kuvastelivat kirkkaassa
auringonpaisteessa.
Komeana ja ylpeänä seisoi hän siinä, ja näyttipä hän todella
mieheltä, joka osasi käskeä, katseensakin oli terävä ja ripeä, mutta
silmänsä olivat nyt levollisemmat kuin aiemmin, ja koko miehessä oli
jotain vakaasti miettivää, punnitsevaa. Sen oli vaikuttanut se päivä,
jona hän oli kärsinyt haaksirikon useamman kuin yhden kerran ja
saarensa suuri valtaava yksinäisyys ja kova työ, jota hän sillä oli
tehnyt.

Saaren ruoholakeutta leikkelivät luonnonmuodostamat tai


ihmiskädellä tehdyt kaivannot, kauas ulos, niinkauas kuin vaan
viherti viherjää ruohoa, ulottuivat nyt ojakaivannot ja maavallit, ja
kauemmas vielä satoja metrejä ulos matalikolle, kurottautuivat lujat
pensas-sulut pidättämään liejua, jota jo oli kerääntynyt, ja
kokoomaan uutta, jota ajelehti niille nousuveden mukana, Pitkä
säikkäjono, saaren turvavarus, oli rauhotettu rautalanka-aitauksella,
niin ett'ei mikään eläin päässyt niille syömään rantavehnää ja
särkemään lautalaitteita. jotka pidättivät lentohiekkaa. Ruohokentällä
taas, tuolla missä nuo lukemattomat ojat viiltelivät maan kamaraa,
käyskeli laitumella kuusisataa lammasta, yli tuhannen hanhea,
kymmenen nuorta joutia, muutamia lehmiä ja kaksi jykeätä hevosta.
Alhaalla vallin juurella laski pieniä lapsia venheitä purjehtimaan
viistoon poikki lammen; ne olivat paimenen ja rengin lapset, jotka
asuivat kivisessä sivurakennuksessa. Punapään savimaja taas oli
lännessä, säikän äärimmäisessä päässä, se oli kyhätty meren
ajamista puista: hänen venheensä oli Dieksander Gattissa.

Tuo kaikki oli rakennettu ja laitettu kuntoon neljässä suvessa, ja oli


sitä suojattu, lujitettu ja korjailtu neljänä yksinäisenä talvena, jolloin
meri myrskyili ympärillä. Frans Strandiger oli lujalla kädellä tarttunut
tehtäviinsä. Aiemmin oli hän pyrkinyt noudattamaan sydämensä
haluja, nyt pyrkii hän työhön, työhön, jota suoritetaan suurten
vakavain suunnitelmain mukaan. Luonteeltaan hän ei ole muuttunut,
päämääränsä ainoastaan ovat muuttuneet. Sentähden näyttääkin
hän ihmisille toiselta.

Büsenista käsin tulla porhaltelee kiitävä venhe. Sen uusi purje


lepää viistoon veden yli. Se purjehtii hyvin.

Hän on keksinyt sen kohta mereltä.

"Aivan oikein, tuolta tulevat he! Tuokion kuluttua saattavat he


laskea maihin jo." Hän lähti tyyneesti ja verkkaan astumaan
rantavallin yli, vei suorsat kyökkiin, ja pyysi Antjea, joka seisoi lieden
ääressä, paistamaan ne. "Tulee vieraita, Antje! Muistatko niitä, jotka
viime kesänä olivat kylpemässä Büsenissä ja neljä kertaa kävivät
purjehtimassa täällä meillä?"

"Tuo neiti Hampuristako, joka viihtyy niin Flackelhnlmilla?"

"Juuri hän! Näin hänet neljätoista päivää sitten Hampurissa. Mutia


tällä kertaa tuo hän ukon mukanaan."

"Noo…" sanoi Antje lyhyeen, "siinä tapauksessa tiedän jo."

"Mitä tiedät?"

"Älkää olko olevinanne!… Te aiotte mennä naimisiin."

"Mutta sinä jäät tänne, Antje! Jokatapauksessa jäät!"

"Noh! Hänen kanssaan tekisin sen! Hän on yksinkertainen


vaatimaton ihminen, ja hän sanoo, että vanhempansa myöskin ovat
yksinkertaisia."
Strandiger naurahti lyhyeen ja lähti ulos. Kun hän tuli vallin harjan
ylitse, olivat he jo laskeneet maihin. Aivan oikein: tuossa tulivat nuo
molemmat: vaaleaverinen tyttö, oikea friesiläisvartalo, pitkä ja
solakka, rinnallaan isänsä, jolla oli päässä laivurilakki, ja
merimiesmäisessä puvussa: ja vaikk'ei hän ollutkaan mikään pieni
mies, ei hän ollut pitempi kuin tyttärensäkään. Frans Strandiger astui
rivakasti heitä vastaan ja kaukaa jo viittoili ukko, hieman hämillään
ja leikkisän näköisenä ja huutaen kovaan: "Flackelholmin kuningas!
Minä tervehdin teitä… No… ettehän pane pahaksenne… vanha
merimies!"

He ravistivat toistensa käsiä ja ymmärsivät paikalla toisiaan.

"No, mitenkä purjehtii venhe neiti Elsa?"

Tämä ei vastannut hänen kysymykseensä, vaan sanoi, luoden


silmänsä ylös häneen: "Te ette koko talveen ole ollut maissa?"

Hän ravisti päätään.

"Mutta tänä kesänä", sanoi neito, "on tullut monta kylpyvierasta


tänne saadakseen nähdä Flackelholmin kuninkaan. Tunnen tuon…
nuo ihmiset tulevat sisämaasta eivätkä ikinä ole nähneet oikeata
aaltoa, ja siksipä ovatkin innostuneet kaikkeen, mikä vaan kantaa
päässään sinistä verkalakkia edes."

Strandiger naurahti: "Mutta te, neiti Elsa, tiedätte, että minä olen
perin tavallinen mies, vieläpä hieman pelkurikin."

"Miten niin?"

"Koska te nyt tänään tarkastatte Flackelholmia ja kaikkea mitä sillä


on."
Tyttö joutui hämilleen: "Minä tarkastan ainoastaan teitä", virkkoi
hän sitte vilpittömästi. "Oletteko uskaliaalla hyvällä mielellä, sitä
tahdoin ainoastaan tietää, ja enhän siinä toki tehne väärin."

Frans Strandiger kääntyi vilkkaasti häntä kohden ja pudisti


voimakkaasti hänen kättään. "Ei, neiti Elsa, siinä ette tee väärin, sillä
minun perääni kysyy niin ylen harva ihminen maailmassa."

Tytön silmät lensivät yht'äkkiä ylös häneen, koko hiilien kasvonsa


säteilivät suurta iloa.

He saapuivat vallille ja nousivat sitä ylös. Elsa lähti tervehtimään


Antjea, kapteeni taas jäi ylös seisomaan, pyyhki hikeä otsaltaan,
katseli ympärilleen ja sanoi. "Elsa on tänä talvena puhunut paljon
teistä ja saarestanne, herra Strandiger. Elsa… tietäkää… on syntynyt
jossain tuolla Tyyneellä Valtamerellä lähellä Uutta-Seeiantia. Kuletin
silloin erästä Apenradilaista laivaa, joka oli matkalla San Fransiskosta
Melbourneen. Olen syntyperää Syltistä, siihen on yhtynyt
Apenradilaista verta. Voimakasta rotua siellä. Siksipä ovat hänellä
siniset silmänsä ja pituutensa. Sitte matkusteli hän kauan
kanssamme. Senpätähden tuntuukin hänestä nyt Hampuri liika
ahtaalta: hänellä pitää olla avara näkyala. Minun on pitänyt
rakennuttaa itselleni tämä venhe, ja olemme tulleet Elbeä alas, hiton
Süderpiep'issä olimme vähällä kärsiä haaksirikon, koska
tähystelimme molemmat Flackelholmia ja sen lipputankoa kohden.
Pojat, jotka minulla ovat, ovat kaikki hyvissä turvissa, kaksi on
kapteenina ja kaksi kauppiaana, toinen Transvaalissa, toinen
Kiinassa; mutta tuo ainoa tyttönen aikaansaa minulle enemmän
huolta, kuin neljä poikaa yhteensä."

"Hänen pitää mennä naimisiin, kapteeni."


"Pitääkö hänen!"

"Niin, ja selittäkääs minulle nyt tämä paikka oikein. Saarihan on


serkkunne omaisuutta vai? Kuinka arvokas se ollee?"

"Sitä on vaikea sanoa. Sitäpaitsi kasvaa siihen maata lisään aina."

"Onko teillä varma välikirja serkkunne kanssa?"

"Olen jonkillainen hänen valtuutettunsa tai hänen


toimennusimehensä. Tämä on kallisarvoinen omaisuus. Täällä on jo
tehty kaivos- ja rakennustöitä kolmenkymmenentuhannen markan
edestä, karjalaumojen arvo nouse yli kahdenkymmenen tuhannen
markan, ja tuolla ulompana, missä kasvaa lisää maata, — näettehän
nuo suorat kaivannot tuolla — siellä tehdään joka vuosi työtä noin
kolmentuhannen markan edestä."

"Mitä sanottekaan!" Hän kääntyi vilkkaasti Strandigeria kohden:


"Mutta teillähän pitää olla rikas rouva."

Strandigerin piti nauraa, niin selvästi paljasti ukko


hämmennyksensä ja pelkonsa.

"Ei…" vastasi hän… "ei rikas rouva, vaan rouva, jolla on rohkeutta,
ja joka mielellään asuu Flackelholmilla! Nähkääs te", sanoi hän,
"tuolla on Büsen. Vanhat laivurit, jotka siellä päiväkaudet seisovat
rannalla, tuntevat kyllä lippumerkkini; mutta kuinka kauan viipyy,
ennenkuin sieltä voi olla täällä, jos täällä sattuu hätää ja tautia? Eipä
ole keveätä nuorelle naiselle asua Flackelholmilla. Ja talvella…"

"Talvella? Minähän luulin, että te olitte täällä ainoastaan


kesäasuntoa?"
Strandiger ravisti päätään. "Neljä talvea olen viettänyt täällä, enkä
nähnyt muita kasvoja ympärilläni kuin väkeni. Voisihan tosin
järjestää niinkin, että asuisi parikolme kuukautta Büsenissä; sillä
tunnenhan jo jotakuinkin, miltä talvi näyttää Flackelholmilla. No,
yhdentekevää… viihdyn ja tyydyn täällä, enkä halua itselleni
parempaa asuntopaikkaa. Olen aina toivonut itselleni omaa suurta
valtakuntaani ja nyt olen saanut semmoisen; mutta naisen, joka
aikoo tänne, pitää tuumia asiata useammin kuin kahdesti."

Elsa tuli ylös vallia, ja astui heidän luokseen.

Strandiger jatkoi: "Tiedänhän, pitäähän olla arkatuntoinen


naiselle; mutta minä en ilkeäisi sietää, jos hän oikuttelisi ja itkisi ja
pyytäisi takaisin mannermaalle. Jään elämäni ajaksi tänne
Flackelholmille: siksipä sanonkin, hänen pitää olla voimakkaan
ruumiiltaan ja sielultaan. Silloinpa ei ole elämä täällä ilman arvoaan
ja ilojaan!

"Katsokaas, kapteeni, taivaanrannalla tuota matalaa maata. Sieltä


voi laskuvedellä tulla tänne jalan tai ratsain tai rattailla. Jos on
tarpeen, ja jos hevoset ovat vahvat, voi tehdä matkan edestakaisin
toisesta laskuvedestä toiseen. Sieltä kohoaa maa tännepäin ja täältä
sinnepäin, ja kaikkialla tiellä on syvää pehmeätä liejua kummallakin
puolen. Tuoltapäin työskentelee hallitus ponnella ja taidolla:
täälläpäin teemme me työtä. Täältä tuonne on veden alla tuhansia
hehtaareja hedelmällisintä maata. Ja juuri sitä se on, jota
tarvitsemme: tuolla tuollapuolen ovat nimittäin tuvat täynnä lapsia.
Jos saan elää ja pysyä voimissani — itse en kyllä ole saava nähdä
sitä saatettuna loppuun, ihmiselämä on liika lyhyt —: mutta jälkeeni,
eikä niin pitkääkään aikaa jälkeeni, on tuossa lainehtiva vehnäpelto
vehnäpellon vieressä, talo seisova talon vieressä, ja ympyrävallin
asujamet ovat sunnuntai-aamuina tekevät matkaa valkeata tietä
kirkolle tornia kohden, jonka näette tuolla. Silloin, jos niin käy, silloin
ovat lapset kerta vielä puhuvat Flackelholmin kuninkaasta, joka on
alkanut työn."

Kapteeni nyökäytti mietteissään jäänharmaata päätään. "Hyvää on


tuo!" sanoi hän vakavasti. "Ja ymmärrän tytärtäni ja toivon, että onni
teitä seuraisi tuossa kaikessa… seuraisi koko elämänne ajan." Sitte
laski hän taas lakin päähänsä ja tuumi: "Käväisen hiukan katsomassa
taloanne, jos sallitte, ja puhuttelemassa emännöitsijäänne, olen
nimittäin väsynyt." Hän lähtikin vallin rinnettä alas rakennusta
kohden, ja seisoi kohta vilkkaassa haastelussa Antjen kanssa lieden
ääressä, jolla suorsat paistuivat.

"Entä me?" kysyi Frans Strandiger.

"Jos haluatte, menemme säikälle, ja istumme siellä penkille, jolla


viime kesänäkin istuimme, ja haastelemme hiukan."

Mutta he eivät ennättäneetkään niin pitkälle, tuli jotain tuiki


vähäpätöistä väliin.

Kun he vierekkäin ja molemmat syvästi liikutettuina astelivat


säikän reunaa pitkässä ruohikossa, istui siellä pesässään,
ruohonkorsien välillä, leivonen, eikä lentänyt ylös, istui vaan ja
taivutteli päätään ja katsoi heihin kumpaankin. Uros istui vieressä.

He seisahtuivat kumpikin. Ja tuo armas suloinen kuva sai


ihmisetkin lähelle toisiaan. Mies ajatteli: "Oi sinua luonto!" Tyttö
ajatteli: "Kuinka armasta ja omaista", ja taivutti päätään.
Silloin ei kestänyt hän enää kauempaa, että neito seisoi siten
rinnallaan. Vanha maltittomuutensa heräsi hänessä ja hän tempaisi
tytön luokseen. Tyttö hillitsi itsensä itkemästä: "Minähän tahdon.
Mutta sinun pitää pitää minusta. Autuas olen oleva."

Leivot eivät liikahtaneetkaan; ne katselivat vaan.

*****

Seuraavana iltana toivat Heim ja Eva Strandigerkartanoon tiedon


kihlauksesta Flackelholmilla, josta Antje oli käynyt ilmoittamassa.
Sokea rouva oli tapansa mukaan istuallaan vuoteessaan. Istuen
vuoteen reunalla kertoi Heim ilolla, joka kuohahteli yli reunojensa,
kihlauksesta. Sokea itki ilosta. Mutta kun Heim silitti hänen hentoja
käsiään ja pyysi häntä hymyilemään, hymyili hän. Sitte kun he
yhdessä istuivat seurusteluhuoneessa, joka oli sokean
makuukammarin vieressä, veti Andrees taskustaan esiin erään
kirjeen. "Minullakin on jotain", sanoi hän, "kirje Hinnerk Elseniltä.
Kuunnelkaa, kun luen sen."

"Hyvä herra Strandiger! Olen saanut kirjeen, jonka Heim on


minulle lähettänyt. Iloitsen että siellä on rakennettu uusia
rakennuksia, joihin kuuluu maatakin, ja että Pellwormer vielä
elää, vaikka hän onkin heikko ja raihnas. Tilamme täällä on
hyvä, meillä on maata ja ruokaa, vaikk'ei mitään käteistä
rahaa; ja yksi meistä on onnellisin ja se on Schütt. Schüttin
kävi näinikään. Kun läksimme kotoa, oli hän sulaa sadattelua
ja rehentelyä: nyt saisivat Eschenwinkel ja Schleswig-Holstein
mennä menojaan vaikka Pohjanmeren pohjaan, hän puhaltaisi
perästä. Hän oli aina niin ruokoton puheissaan. Semmoinen
oli hän koko matkan, ja vielä puolen vuotta täälläkin. Sitte ei
hän enää löytänyt lepoa maapalstalla, jonka hän oli
vuokrannut. Hän rupesi kuleksimaan kaupustelijana farmilta
farmille, ja kun hän oli vilkaspuheinen mies, sai hän tavaransa
hyvin kaupoiksi, varsinkin englantilaisten kesken, koska hän
aina herjasi Saksaa. Hän kertoi heille tarkalleen, millaista
kotiseudulla on. Kuvasi kankaat, lammen, rantavallin,
kiertelevät tiet, kylän ja kirkon ja lopuksi sanoi hän: 'Nähkääs,
tuommoinen kiero maa! Mutta täällä, Iowassa, täällä on kaikki
suoraa!' Siten sanoi hän. Hänhän on saanut oppia koulussa.
Mutta lankesipa lopulta omaan kuoppaansa! Kerran oli hän
taas juonut itsensä humalaan, ja herjaili taaskin Schleswig-
Holsteinia. Silloin rupesivat englantilaiset laulamaan erästä
pilkkalaulua saksalaisista. Silloin rupeaa hän yht'äkkiä
itkemään ja huitoo käsillään ympärilleen ja kirkuu: 'He eivät
saa sanoa sanaakaan Schleswig-Holsteinistä!' Se oli muka
paras maa maanpäällä! Ja oli alkanut kertoa kankaasta,
rantavallista ja kanavasta. Ja niinpä ilmeni, että koti-ikävä oli
saanut miehen sekaisin. Ja on vielä sekaisin. Tekee kyllä
työnsä, ei juokkaan, mutta illat istuu hän huoneensa
edustalla, kyhää pienen rantavallin, muovaa mullasta ja
pienistä kivistä kankaan reunan, kirkon ja kylän, ja tekee sen
niin taitavasti, että me toiset sunnuntaisin välistä menemme
hänen luokseen, ja seisomme kaikki hänen ympärillään. Ja
silloin puhuu hän yhtä jaksoa tuosta vanhasta kierästä
maasta. Mutta hän luulee, ett'ei hän enää ikinä voi palata
sinne, ja kuvittelee, kuin olisi se kuussa ja viettää oikein
onnellisiakin päiviä. Me samoin, ja Anna käskee lähettää
terveisensä, on kelpo vaimo. Maissi ei maksa mitään, siat
neljä dollaria, olemme itse teurastaneet ne.

Hinnerk Elsen, tarmari."


Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

ebooknice.com

You might also like