DSL is simply a Domain Specific Language. You can use DSLs that apply to a specific domain instead of a general purpose language (like Kotlin). You may write a DSL that defines the layout of a UI, or the flow of materials through a factory, or in the case of Gradle, how to build your application.
You could implement a DSL by writing an interpreter and defining a grammar, but for most cases, it's easier to accept a common syntax and exploit the structure and language features of your host language to only define the necessary semantics.
Similar to Groovy, which has expando objects, as well as the ability to pass closures which can be placed outside the parameter list when passed as the final parameter, you can exploit these language features to cleanly define your DSL.
When using the DSL, you don't need to worry about the implementation; simply use the structure defined to get the outcome you want. In the case of Gradle, you have top-level items such as plugins, dependencies, and configurations all of which have sub-items that are only valid within their respective scope.
Kotlin for the most part has what is called an internal DSL meaning you would use the syntax of the DSL directly inside your source code. It's also possible to define an external DSL which is a file solely consisting of the DSL which might for example be created by clients of the application.
You might encounter DSLs all the time - for defining your infrastructure, your tests, your deployment procedures, or even querying the Database (SQL is a DSL).
As relates to Gradle there are two variants, build.gradle actually uses Groovy as its engine while build.gradle.kts uses Kotlin. The difference is in the language features being exploited to produce the syntax of the DSL.